% \iffalse
% --------------------------------------------------------------------
%<*hex>
% \fi
% 
% \subsubsection{Hex coordinate system}
%
% \begin{Macro}{\hex@xx,\hex@yy}
% 
%   Some offsets along $x$ and $y$ due to offset of every second hex
%   column.
%
%   \begin{align*}
%       \delta_x &= \cos60^{\circ}\\
%       \delta_y &= \sin60^{\circ}\\
%   \end{align*}
%
%   These numbers are calculated once here and then used several times
%   in the following code.
%
%    \begin{macrocode}
\pgfmathparse{cos(60)}        \xdef\hex@xx{\pgfmathresult}
\pgfmathparse{sin(60)}        \xdef\hex@yy{\pgfmathresult}
\pgfmathparse{\hex@yy*cos(30)}\xdef\hex@e@xx{\pgfmathresult}
\pgfmathparse{\hex@yy*sin(30)}\xdef\hex@e@yy{\pgfmathresult}
\newdimen\hex@radius\hex@radius=1cm
\newdimen\hex@dx    \expandafter\hex@dx=\hex@xx cm
\newdimen\hex@dy    \expandafter\hex@dy=\hex@yy cm
\newdimen\hex@e@dx  \expandafter\hex@e@dx=\hex@e@xx cm
\newdimen\hex@e@dy  \expandafter\hex@e@dy=\hex@e@yy cm

%    \end{macrocode}
% \end{Macro}
%
% Some code we need for some options
%
%    \begin{macrocode}
\newif\ifhex@label@is@name\hex@label@is@namefalse
\def\hex@short@col{isfalse}
\def\hex@got@short{isfalse}
\pgfmathdeclarefunction{isfalse}{1}{%
  \begingroup
  \def\pgfmathresult{0}%
  \pgfmath@smuggleone\pgfmathresult
  \endgroup}
\pgfmathdeclarefunction{istrue}{1}{%
  \begingroup
  \def\pgfmathresult{1}%
  \pgfmath@smuggleone\pgfmathresult
  \endgroup}
%    \end{macrocode}
%
% What follows is a way to configure the hex coordinate system.  For
% example, if the rows goes down, then we can flag that, but still add
% hexes straightforwardly.  Similar for columns.  We can also specify
% that the first row or column has number 1 (instead of 0).  Since
% this is dealt with a the coordinate level, it means most of the rest
% of the code is agnostic to these choices. 
% 
% Which is the first coordinate (0 or 1)
%
%    \begin{macrocode}
\tikzset{
  hex/first row is/.is choice,
  hex/first row is/0/.code={\def\hex@coords@row@off{0}},
  hex/first row is/1/.code={\def\hex@coords@row@off{-1}},
  hex/first row is=0,
  hex/first column is/.is choice,
  hex/first column is/0/.code={\def\hex@coords@col@off{0}},
  hex/first column is/1/.code={\def\hex@coords@col@off{-1}},
  hex/first column is=0,
  hex/first row and column are/.is choice,
  hex/first row and column are/0/.style={
    hex/first row is=0,%
    hex/first column is=0},
  hex/first row and column are/1/.style={
    hex/first row is=1,%
    hex/first column is=1},
%    \end{macrocode}
% 
% Which way does the column and row numbers go
%
%    \begin{macrocode}
  hex/row direction is/.is choice,
  hex/row direction is/normal/.code={\def\hex@coords@row@fac{1}},
  hex/row direction is/reversed/.code={\def\hex@coords@row@fac{-1}},
  hex/row direction is/up/.style={hex/row direction is=normal},
  hex/row direction is/down/.style={hex/row direction is=reversed},
  hex/row direction is/positive/.style={hex/row direction is=normal},
  hex/row direction is/negative/.style={hex/row direction is=reversed},
  hex/row direction is=normal,
  hex/column direction is/.is choice,
  hex/column direction is/normal/.code={\def\hex@coords@col@fac{1}},
  hex/column direction is/reversed/.code={\def\hex@coords@col@fac{-1}},
  hex/column direction is/right/.style={hex/column direction is=normal},
  hex/column direction is/left/.style={hex/column direction is=reversed},
  hex/column direction is/positive/.style={hex/column direction is=normal},
  hex/column direction is/negative/.style={hex/column direction is=reversed},
  hex/column direction is=normal,
%    \end{macrocode}
% 
% Make labels names of shapes of the hexes so we can use labels to
% place stuff
%
%    \begin{macrocode}
  hex/label is name/.is if=hex@label@is@name,
%    \end{macrocode}
% 
% If we have uneven number of rows in some columns. 
%
%    \begin{macrocode}
  hex/short bottom columns/.is choice,
  hex/short bottom columns/odd/.code={%
    \def\hex@bot@short@col{isodd}
    \def\hex@got@bot@short{istrue}
    \hex@dbg{4}{Short columns (odd): \meaning\hex@bot@short@col}},
  hex/short bottom columns/even/.code={
    \def\hex@bot@short@col{iseven}
    \def\hex@got@bot@short{istrue}
    \hex@dbg{4}{Short column (even): \meaning\hex@bot@short@col}},
  hex/short bottom columns/none/.code={
    \def\hex@bot@short@col{isfalse}
    \def\hex@got@bot@short{isfalse}
    \hex@dbg{4}{Short columns (none): \meaning\hex@bot@short@col}},
  hex/short bottom columns=none,
  hex/short columns/.forward to=hex/short bottom columns,
  hex/short top columns/.is choice,
  hex/short top columns/odd/.code={%
    \def\hex@top@short@col{isodd}
    \def\hex@got@top@short{istrue}
    \hex@dbg{4}{Short columns (odd): \meaning\hex@top@short@col}},
  hex/short top columns/even/.code={
    \def\hex@top@short@col{iseven}
    \def\hex@got@top@short{istrue}
    \hex@dbg{4}{Short column (even): \meaning\hex@top@short@col}},
  hex/short top columns/none/.code={
    \def\hex@top@short@col{isfalse}
    \def\hex@got@top@short{isfalse}
    \hex@dbg{4}{Short columns (none): \meaning\hex@top@short@col}},
  hex/short top columns=none,
}
\message{^^JInitial hex coordinate setup:
  Rows: factor=\hex@coords@row@fac, offset=\hex@coords@row@off
  Columns: factor=\hex@coords@col@fac, offset=\hex@coords@col@off}
%    \end{macrocode}
% 
% \begin{HexKey*}{
%   hex/coords/column,
%   hex/coords/row,
%   hex/coords/vertex,
%   hex/coords/edge,
%   hex/coords/offset}
%
%   We define the keys for hexagon coordinates.  These are the
%   \spec{row}, \spec{column}, possible \spec{vertex} or
%   \spec{edge}. Vertexes and edges are defined as
%   multiple-choice. \spec{offset} specifies the offset from the
%   centre in the direction of a vertex or edge.  By default, the
%   offset is one, meaning all the way to the vertex or edge.
%
%   The key \spec{inverse row} specifies that the rows are given from
%   the top down, but coordinates should be calculated as if the row
%   was negative.  This (should) allow us to design boards where rows
%   increase downward, while still keeping the interface and remaining
%   code somewhat reasonable and agnostic.
%
%   Similarly, the key \spec{column 1}, will allow us to start the
%   columns with 1.
%
% 
%
%    \begin{macrocode}
\tikzset{
  /hex/coords/.cd,
  column/.store in=\hex@col,
  c/.store in=\hex@col,
  row/.store in=\hex@row,
  r/.store in=\hex@row,
  offset/.store in=\hex@off,
  o/.store in=\hex@off,
  vertex/.is choice,
  vertex/none/.code={\global\let\hex@vtx\@empty},
  vertex/east/.code={\def\hex@vtx{0}},
  vertex/north east/.code={\def\hex@vtx{60}},
  vertex/north west/.code={\def\hex@vtx{120}},
  vertex/west/.code={\def\hex@vtx{180}},
  vertex/south west/.code={\def\hex@vtx{240}},
  vertex/south east/.code={\def\hex@vtx{300}},
  vertex/E/.code={\def\hex@vtx{0}},
  vertex/NE/.code={\def\hex@vtx{60}},
  vertex/NW/.code={\def\hex@vtx{120}},
  vertex/W/.code={\def\hex@vtx{180}},
  vertex/SW/.code={\def\hex@vtx{240}},
  vertex/SE/.code={\def\hex@vtx{300}},
  vertex/.default=none,
  v/.forward to=/hex/coords/vertex=#1,
  edge/.is choice,
  edge/none/.code={\global\let\hex@edg\@empty},
  edge/north east/.code={\def\hex@edg{30}},
  edge/north/.code={\def\hex@edg{90}},
  edge/north west/.code={\def\hex@edg{150}},
  edge/south west/.code={\def\hex@edg{210}},
  edge/south/.code={\def\hex@edg{270}},
  edge/south east/.code={\def\hex@edg{330}},
  edge/NE/.code={\def\hex@edg{30}},
  edge/N/.code={\def\hex@edg{90}},
  edge/NW/.code={\def\hex@edg{150}},
  edge/SW/.code={\def\hex@edg{210}},
  edge/S/.code={\def\hex@edg{270}},
  edge/SE/.code={\def\hex@edg{330}},
  edge/.default=none,
  e/.forward to=/hex/coords/edge,
}
%    \end{macrocode}
% \end{HexKey*}
%
% \begin{Macro}{\hex@coords@reset}
%
%   This macro resets the hex coordinates to default values.  That is
%   row and column 0, no vertex or edge.
%   
%    \begin{macrocode}
\def\hex@coords@reset{%
  \tikzset{%
    /hex/coords/.cd,
    column=0,
    row=0,
    edge=none,
    vertex=none,
    offset=1}}
%    \end{macrocode}
% \end{Macro}
% 
% The following calculates the Cartesian coordinates from Hex
% coordinates
%
% \begin{Syntax}
%   (cs:hex column=\meta{C},row=\meta{R},vertex=\meta{V},edge=\meta{E})
% \end{Syntax}
%
% Given the hexagon column $C$ and row $R$ with hexagon radius $r$,
% the centre of the hexagon is at 
%
% \begin{eqnarray*}
%     x &=& 2C\frac{3}{4}r\\
%     y &=& r(R - (C \% 2)\sin60^{\circ})
%   \end{eqnarray*}
%
% If \meta{V} or \meta{E} are given, then these are added to the
% centre point.
%
% Note, $C$ and $R$ may be fractional numbers, which will specify a
% point inside a hex.
%
% We set-up the translation to Cartesian coordinates. First
% thing is to reset keys in \spec{/hex/coords}, and then parse out the
% keys given.
% 
%    \begin{macrocode}
\def\hex@coords@conv#1{%
  \hex@coords@reset%
  \tikzset{/hex/coords/.cd, #1}%
%    \end{macrocode}
%
% Then we calculate the $x$ coordinate and set the dimension
% \cs{pgf@x}. We do this by
%
% $$x=c_e \frac{3}{2}\quad,$$
%
% where
%
% $$c_e = f_c  (c+o_c)\quad,$$ 
%
% is the effective column (stored in \cs{hex@eff@col}) calculated from
% is the direction factor $f_c$ (set by \spec{hex/column direction
% is}) and the offset $o_c$ (set by \spec{hex/first column is}).
% 
%    \begin{macrocode}
  \pgfmathparse{int(\hex@coords@col@fac*(\hex@col+\hex@coords@col@off))}%
  \xdef\hex@eff@col{\pgfmathresult}%
  \hex@dbg{2}{Effective column: \hex@coords@col@fac * (\hex@col +
    \hex@coords@col@off) -> \hex@eff@col}%
  \pgfmathparse{\hex@eff@col*1.5}%
  \xdef\hex@x{\pgfmathresult}%
%    \end{macrocode}
%
% And then for the $y$ coordinate and set the dimension \cs{pgf@y}.
% 
% $$y  = 2\left(r_e - c_e \operatorname{mod} 2\right) \cos60^{\circ}\quad,$$
%
% where
% 
% $$r_e= 2 f_r (r+o_r) - (c+o_c) \operatorname{mod} 2\quad,$$
%
% is the effective row (stored as \cs{hex@eff@row}) calculated from
% the the direction factor $f_r$ (set by \spec{hex/row
% direction is}) and the offset $o_r$ (set by \spec{hex/first
% row is}). 
% 
%    \begin{macrocode}
  \pgfmathparse{int(\hex@coords@row@fac*(\hex@row+\hex@coords@row@off))}%
  \xdef\hex@eff@row{\pgfmathresult}%
  \hex@dbg{2}{Effective row: \hex@coords@row@fac * (\hex@row +
    \hex@coords@row@off) -> \hex@eff@row}%
  %\pgfmathparse{(2*\hex@eff@row-mod(round((\hex@col+\hex@coords@col@off)),2))*\hex@yy}%
  \pgfmathparse{(2*\hex@eff@row-mod(abs(round(\hex@col+\hex@coords@col@off)),2))*\hex@yy}%  
  \xdef\hex@y{\pgfmathresult}%
%    \end{macrocode}
%
% If we have a vertex specification add that location to the current
% coordinates.  If not, set the point. 
% 
%    \begin{macrocode}
  \ifx\hex@vtx\@empty\else%
    \pgfmathparse{\hex@x+\hex@off*cos(\hex@vtx)}\xdef\hex@x{\pgfmathresult}
    \pgfmathparse{\hex@y+\hex@off*sin(\hex@vtx)}\xdef\hex@y{\pgfmathresult}
  \fi%
  % \ifx\hex@vtx\@empty\pgfpointxy{\hex@x}{\hex@y}\else%
  % \pgfpointadd{\pgfpointxy{\hex@x}{\hex@y}}{%
  %   \pgfpointscale{\hex@off}{\pgfpointpolarxy{\hex@vtx}{1}}}\fi%
%    \end{macrocode}
%
% If we have an edge specification add that location to the current
% coordinates.  
% 
%    \begin{macrocode}
  \ifx\hex@edg\@empty\else%
    \pgfmathparse{\hex@x+\hex@off*\hex@yy*cos(\hex@edg)}%
    \xdef\hex@x{\pgfmathresult}%
    \pgfmathparse{\hex@y+\hex@off*\hex@yy*sin(\hex@edg)}%
    \xdef\hex@y{\pgfmathresult}%
  \fi%
  % \ifx\hex@edg\@empty\else%
  % \pgfpointadd{\pgfpointxy{\hex@x}{\hex@y}}{%
  %   \pgfpointscale{\hex@off}{\pgfpointpolarxy{\hex@edg}{\hex@yy}}}\fi
%    \end{macrocode}
%
% For debugging, we can print out stuff. 
% 
%    \begin{macrocode}
  \pgfpointxy{\hex@x}{\hex@y}    
  \hex@dbg{2}{Hex coordinates: #1
    ^^J c=`\hex@col'
    ^^J r=`\hex@row'
    ^^J v=`\hex@vtx'
    ^^J e=`\hex@edg'
    ^^J o=`\hex@off'
    ^^J x=`\hex@x'
    ^^J y=`\hex@y'}%
  \global\let\hex@x\hex@x%
  \global\let\hex@y\hex@y%
  \global\let\hex@row\hex@row%
  \global\let\hex@col\hex@col%
}
\tikzdeclarecoordinatesystem{hex}{%
  \hex@coords@conv{#1}}
%    \end{macrocode}
% \iffalse
%</hex>
% --------------------------------------------------------------------
% \fi 
