% \iffalse % -------------------------------------------------------------------- %<*hex> % \fi % % \subsubsection{Board clipping and frame} % % \begin{Macro}{\boardframe} % % Define the bounding box around the board % % \begin{Syntax} % \cs{boardframe}\oarg{margin}\parg{lower=left}\parg{upper-right}\marg{margin} % \end{Syntax} % % where \meta{lower-left} and \meta{upper-right} specifies the lower % left and upper right hexes (inclusive) of the board. % % % \begin{macrocode} \def\boardframe{% \@ifnextchar[{\bo@rdframe}{\bo@rdframe[0]}%] } % \end{macrocode} % % Below is our new implementation of \cs{boardframe}. This is split % into parts. % % % First, a macro that will define the path around rectangular placed % hexes. This takes 4 mandatory arguments: lower left column and row, % and upper right column and row, in that order. It also accepts an % optional argument. If this is not empty, then it is assumed to be a % style to apply, and hexes will be drawn using that style. The style % will be passed the hex coordinates and can react accordingly. % % \begin{macrocode} \def\bo@rdfr@me{ \@ifnextchar[{\bo@rdfr@me@}{\bo@rdfr@me@[]}%] } \def\bo@rdfr@me@u(#1)#2#3#4#5{ \hex@coords@conv{#1} % \hex@dbg{0}{#1 -> `\hex@x',`\hex@y'} \pgfmathparse{min(#2,\hex@x)}\xdef#2{\pgfmathresult} \pgfmathparse{min(#3,\hex@y)}\xdef#3{\pgfmathresult} \pgfmathparse{max(#4,\hex@x)}\xdef#4{\pgfmathresult} \pgfmathparse{max(#5,\hex@y)}\xdef#5{\pgfmathresult} \hex@dbg{2}{#1 -> ll=`#2',`#3', ur=`#4',`#5'} } \def\bo@rdfr@me@[#1]#2#3#4#5{ % Define rtmp and a ctmp to by directions \pgfmathparse{int(\hex@coords@row@fac)}\edef\rtmp{\pgfmathresult} \pgfmathparse{int(\hex@coords@col@fac)}\edef\ctmp{\pgfmathresult} % Define vertices for path \def\ctfv{SW} \def\ctsv{SE} \def\cbfv{NE} \def\cbsv{NW} \def\rrfv{E} \def\rrsv{NE} \def\rlfv{W} \def\rlsv{SW} % Swap around some definitions based on the row direction \ifnum\rtmp<0 \let\max@short\hex@bot@short@col \let\min@short\hex@top@short@col \let\swp\ctfv\let\ctfv\cbsv\let\cbsv\swp \let\swp\ctsv\let\ctsv\cbfv\let\cbfv\swp \def\rrsv{SE} \def\rlsv{NW} \else \let\max@short\hex@top@short@col \let\min@short\hex@bot@short@col \fi % Swap around some definitions based on the column direction \ifnum\ctmp<0 \let\swp\ctfv\let\ctfv\ctsv\let\ctsv\swp \let\swp\cbfv\let\cbfv\cbsv\let\cbsv\swp \let\swp\rrfv\let\rrfv\rlsv\let\rlsv\swp \let\swp\rrsv\let\rrsv\rlfv\let\rlfv\swp \fi % Define tmp = 0 if no shorts, 1 if top short, 2 if both \pgfmathparse{ifthenelse(\hex@got@top@short, ifthenelse(\hex@got@bot@short,2,1),0)}\edef\tmp{\pgfmathresult} % If top-short, set factors \ifnum\tmp=1 \def\mnf{-1} \def\mxf{-1} \def\mnn{} \def\mxn{} % If both short, set factors \else\ifnum\tmp=2 \def\mnf{\rtmp} \def\mxf{(-\rtmp)} % If inverse rows, set factors \ifnum\rtmp<0 \def\mnn{} \def\mxn{not} \else \def\mnn{not} \def\mxn{} \fi % If none is short \else \def\mnf{1} \def\mxf{1} \def\mnn{not} \def\mxn{not} \fi\fi % Define row@mn to give least row of column \def\row@mn##1{% \pgfmathparse{int(#3+\mnf* \hex@coords@row@fac*\min@short(##1)* \mnn(\min@short(\hex@coords@col@off)))} \edef\lr{\pgfmathresult}} % Define row@mx to give largest row of column \def\row@mx##1{% \pgfmathparse{int(#5+\mxf* \hex@coords@row@fac*\max@short(##1)* \mxn(\max@short(\hex@coords@col@off)))} \edef\ur{\pgfmathresult}} % % % Below defines a path around the perimeter of the hexes. % \def\@llx{10000} \def\@lly{10000} \def\@urx{-10000} \def\@ury{-10000} % Start with an empty path \def\p{} % Loop across least row (can be top if \rtmp<0) \foreach \c in {#2,...,#4}{% \row@mn{\c} \row@mx{\c} % \message{^^JColumn: `\c' -> `\lr',`\ur' (#3,#5)} } \foreach \c in {#2,...,#4}{% \row@mn{\c} \xdef\p{\p (hex cs:c=\c,r=\lr,v=\ctfv)-- (hex cs:c=\c,r=\lr,v=\ctsv)--} \bo@rdfr@me@u(c=\c,r=\lr,v=\ctfv)\@llx\@lly\@urx\@ury \bo@rdfr@me@u(c=\c,r=\lr,v=\ctsv)\@llx\@lly\@urx\@ury } % Go up (down if \rtmp<0) right side \row@mn{#4} \row@mx{#4} \foreach \r in {\lr,...,\ur}{% \xdef\p{\p (hex cs:c=#4,r=\r,v=\rrfv)-- (hex cs:c=#4,r=\r,v=\rrsv)--} \bo@rdfr@me@u(c=#4,r=\r,v=\rrfv)\@llx\@lly\@urx\@ury \bo@rdfr@me@u(c=#4,r=\r,v=\rrsv)\@llx\@lly\@urx\@ury } % Go across largest row (can be bottom if \rtmp<0) \foreach \c in {#4,...,#2}{% \row@mx{\c} % \message{^^JColumn: `\c', max:`\ur'} \xdef\p{\p (hex cs:c=\c,r=\ur,v=\cbfv)-- (hex cs:c=\c,r=\ur,v=\cbsv)--} \bo@rdfr@me@u(c=\c,r=\ur,v=\cbfv)\@llx\@lly\@urx\@ury \bo@rdfr@me@u(c=\c,r=\ur,v=\cbsv)\@llx\@lly\@urx\@ury } % Go up (down if \rtmp<0) left side. \row@mn{#2} \row@mx{#2} \foreach \r in {\ur,...,\lr}{% \xdef\p{\p (hex cs:c=#2,r=\r,v=\rlfv)-- (hex cs:c=#2,r=\r,v=\rlsv)--} \bo@rdfr@me@u(c=#2,r=\r,v=\rlfv)\@llx\@lly\@urx\@ury \bo@rdfr@me@u(c=#2,r=\r,v=\rlsv)\@llx\@lly\@urx\@ury } % End path with cycle \edef\p{\p cycle} % Define global path \global\let\hex@board@path\p \hex@dbg{3}{Hex board path: `\meaning\hex@board@path'} % If an optional argument was given, then use that to actually make % hexes. \ifx|#1|\else \foreach[count=\nc] \c in {#2,...,#4}{% \row@mn{\c} \row@mx{\c} \foreach \r in {\lr,...,\ur}{% \hex[#1={\c,\r}](c=\c,r=\r) } } \fi } % \end{macrocode} % % % This is a no operations style used as default for the macro % \cs{boardhexes} below. % % \begin{macrocode} \tikzset{% /hex/board/no op/.style args={#1,#2}{}} % \end{macrocode} % % This macro will make the actual hexes using the specified, optional, % style. It builds on \cs{bo@rdfr@me} above. % % \begin{macrocode} \def\boardhexes{% \@ifnextchar[{\bo@rdhexes}{\bo@rdhexes[board/no op]}%] } \def\bo@rdhexes[#1](#2)(#3){% \hex@coords@conv{#2} \edef\llc{\hex@col} \edef\llr{\hex@row} \hex@coords@conv{#3} \edef\urc{\hex@col} \edef\urr{\hex@row} \bo@rdfr@me[#1]{\llc}{\llr}{\urc}{\urr}} % \end{macrocode} % % Creates a board frame using \cs{bo@rdfr@me}. % % \begin{macrocode} \tikzset{board frame bb/.code={ \pgfkeys{ %/tikz/local bounding box=tmp board frame, /tikz/transform shape, /tikz/execute at end scope={% % \hex@dbg{1}{Getting board frame BB} %\wg@get@bb{tmp board frame} \global\let\llx\@llx \global\let\lly\@lly \global\let\urx\@urx \global\let\ury\@ury % \hex@dbg{0}{Board bounding box (\llx,\lly)x(\urx,\ury)} }}}} \def\bo@rdframe[#1](#2)(#3){% \hex@coords@conv{#2} \edef\llc{\hex@col} \edef\llr{\hex@row} % \hex@coords@conv{#3} \edef\urc{\hex@col} \edef\urr{\hex@row} % \def\margin{#1} % % This will store the bounding box in tmp node `board frame' \bo@rdfr@me{\llc}{\llr}{\urc}{\urr}% \begin{scope}[board frame bb] \expandafter\path\hex@board@path; \end{scope} \hex@dbg{1}{Board frame LL: -> `\llx',`\lly'} \pgfmathparse{\llx+ifthenelse(\llx<0,-1,1)*\margin}\edef\llx{\pgfmathresult} \pgfmathparse{\lly+ifthenelse(\lly<0,-1,1)*\margin}\edef\lly{\pgfmathresult} % \hex@dbg{1}{Board frame UR: -> `\urx',`\ury'} \pgfmathparse{\urx+ifthenelse(\urx<0,-1,1)*\margin}\edef\urx{\pgfmathresult} \pgfmathparse{\ury+ifthenelse(\ury<0,-1,1)*\margin}\edef\ury{\pgfmathresult} % \pgfmathparse{\urx-\llx}\edef\w{\pgfmathresult} \pgfmathparse{\ury-\lly}\edef\h{\pgfmathresult} %% Print to the log \hex@dbg{0}{Board Frame: (\llx,\lly)x(\urx,\ury) (\w x\h) (\llc,\llr)x(\urc,\urr)} %% Possibly draw \draw[hex/board frame/.try](\llx,\lly) rectangle(\urx,\ury); %% Store macros \xdef\boardXmin{\llx}% \xdef\boardYmin{\lly}% \xdef\boardXmax{\urx}% \xdef\boardYmax{\ury}% } % \end{macrocode} % % \end{Macro} % % \begin{Macro}{\boardclip} % % Clip the board to not show incomplete hexes % % \begin{Syntax} % \cs{boardclip}\marg{nx}\marg{ny}\marg{preaction} % \end{Syntax} % \begin{macrocode} \def\boardpath(#1)(#2){ \hex@coords@reset% \tikzset{/hex/coords/.cd, #1} \edef\llc{\hex@col} \edef\llr{\hex@row} %% \hex@coords@reset% \tikzset{/hex/coords/.cd, #2} \edef\urc{\hex@col} \edef\urr{\hex@row} % This will store the bounding box in tmp node `board frame' \bo@rdfr@me{\llc}{\llr}{\urc}{\urr}% %% Use the path to extract the bounding box %\begin{scope}[local bounding box=board frame] % \expandafter\path\hex@board@path; %\end{scope} \global\let\hexboardpath\hex@board@path } % \end{macrocode} % \begin{macrocode} \def\boardclip(#1)(#2)#3{% \boardpath(#1)(#2) \draw \ifx|#3|\else[preaction={#3}]\fi% [clip] \hexboardpath; } % \end{macrocode} % \end{Macro} % % % \begin{Macro}{\debuggrid} % % Show a debug grid. This requires \cs{boardframe}. % % \begin{macrocode} \def\debuggrid{% \foreach \i in {0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1} {% \pgfmathparse{\i*\boardW+\boardXmin}% \edef\debug@x{\pgfmathresult}% \draw [very thin,gray](\debug@x,\boardYmin) -- (\debug@x,\boardYmax) node [below,rotate=90] at (\debug@x,\boardYmin) {$\i$}; }% \foreach \i in {0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1} {% \pgfmathparse{\i*\boardH+\boardYmin}% \edef\debug@x{\pgfmathresult}% \draw [very thin,gray] (\boardXmin,\debug@x) -- (\boardXmax,\debug@x) node [left,rotate=90] at (\boardXmin,\debug@x) {$\i$}; } } % \end{macrocode} % \end{Macro} % % Some dummy styles. These will be defined by the export class to % facilitate getting information from the board. % % \begin{macrocode} \tikzset{% zoned/.style={}, zone scope/.style={}, zone path/.style={} } % \end{macrocode} % \iffalse % % -------------------------------------------------------------------- % \fi