% \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} % \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}% \@ifnextchar;{\@gobble}{}% } % \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% \@ifnextchar;{\@gobble}{}% } % \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