summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/wargame/source/hex/coord.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/wargame/source/hex/coord.dtx')
-rw-r--r--macros/latex/contrib/wargame/source/hex/coord.dtx350
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