diff options
Diffstat (limited to 'macros/latex/contrib/wargame/source/hex/coord.dtx')
-rw-r--r-- | macros/latex/contrib/wargame/source/hex/coord.dtx | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/macros/latex/contrib/wargame/source/hex/coord.dtx b/macros/latex/contrib/wargame/source/hex/coord.dtx new file mode 100644 index 0000000000..b996ffa3c2 --- /dev/null +++ b/macros/latex/contrib/wargame/source/hex/coord.dtx @@ -0,0 +1,350 @@ +% \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}% + \expandafter\pgf@x=\hex@x cm% +% \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}% + \xdef\hex@y{\pgfmathresult}% + \expandafter\pgf@x=\hex@y cm% +% \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\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% + \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} + \hex@dbg{2}{Hex coordinates: #1 + ^^J c=\hex@col + ^^J r=\hex@row + ^^J v=\hex@vtx + ^^J e=\hex@edg + ^^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 |