% \iffalse % -------------------------------------------------------------------- %<*hex> % \fi % % \subsubsection{Hexes} % \label{sec:impl:hex:hex} % % In this part, we make macros etc. for the hexes. % % A hex shape. We make a node of this shape if we are to give a name % to the hex added. We add a bunch of anchors to it so we may easily % refer to it. This is also where we actual fill stuff into the hex, % such as terrain and so on. % % \begin{macrocode} \tikzset{% /hex/.cd, bev/.store in=\hex@bevel, bev/.initial=, bevel fraction/.store in=\hex@bevel@frac,bevel fraction/.initial=10, bevel/.is choice, bevel/none/.style = {/hex/bev=}, bevel/north west/.style = {/hex/bev=1}, bevel/north east/.style = {/hex/bev=2}, bevel/south west/.style = {/hex/bev=3}, bevel/south east/.style = {/hex/bev=4}, bevel/NW/.style = {/hex/bev=1}, bevel/NE/.style = {/hex/bev=2}, bevel/SW/.style = {/hex/bev=3}, bevel/SE/.style = {/hex/bev=4}, bevel/.default = {north west}, } \def\hex@bevel@frac{10} \tikzset{ hex/bevel highlight/.style={fill=white,opacity=.25}, hex/bevel shadow/.style={fill=black,opacity=.25}, } % \end{macrocode} % % % % \begin{macrocode} \newdimen\wg@tmpe \newdimen\wg@tmpf \newdimen\wg@tmpg \def\hex@bevel@path#1{% \scope[#1] \wg@tmpe=\wg@tmpa\multiply\wg@tmpe by \hex@bevel@frac \wg@tmpf=\wg@tmpb\multiply\wg@tmpf by \hex@bevel@frac \wg@tmpg=\wg@tmpc\multiply\wg@tmpg by \hex@bevel@frac \divide\wg@tmpe100 \divide\wg@tmpf100 \divide\wg@tmpg100 % Start \pgfpathmoveto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}% % Left \pgfpathlineto{\pgfqpoint{-\wg@tmpa}{\wg@tmpb}}% % Left-down \pgfpathlineto{\pgfqpoint{\wg@tmpc}{\wg@tmpd}}% % Right down \wg@tmpa=-\wg@tmpa% \wg@tmpb=-\wg@tmpb% \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}% % Up, in \advance\wg@tmpa\wg@tmpe% \advance\wg@tmpb\wg@tmpf% \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}% % Left-down, in \advance\wg@tmpc-\wg@tmpg \pgfpathlineto{\pgfqpoint{\wg@tmpc}{\wg@tmpd}}% % Left, down in \advance\wg@tmpb-\wg@tmpf\wg@tmpb-\wg@tmpb% \advance\wg@tmpb-\wg@tmpf \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}% % Start, down in \advance\wg@tmpa-\wg@tmpe\wg@tmpa-\wg@tmpa% \advance\wg@tmpa-\wg@tmpe \pgfpathlineto{\pgfqpoint{\wg@tmpa}{\wg@tmpb}}% % % \pgfclosepath% \pgfusepath{fill} \endscope}% % \end{macrocode} % % % % \begin{macrocode} \hex@dbg{5}{Base vertex: \hex@xx,\hex@yy} \hex@dbg{5}{Base edges: \hex@e@xx,\hex@e@yy} \pgfdeclareshape{hex/hex}{% \saveddimen\radius{\pgf@x=\hex@radius} \savedanchor{\east}{ \pgfqpoint{ \hex@radius}{0cm}} \savedanchor{\west}{ \pgfqpoint{-\hex@radius}{0cm}} \savedanchor{\northeast}{ \pgfqpoint{ \hex@dx}{ \hex@dy}} \savedanchor{\northwest}{ \pgfqpoint{-\hex@dx}{ \hex@dy}} \savedanchor{\southwest}{ \pgfqpoint{-\hex@dx}{-\hex@dy}} \savedanchor{\southeast}{ \pgfqpoint{ \hex@dx}{-\hex@dy}} \savedanchor{\northedge}{ \pgfqpoint{ 0cm}{ \hex@dy}} \savedanchor{\southedge}{ \pgfqpoint{ 0cm}{-\hex@dy}} \savedanchor{\northeastedge}{\pgfqpoint{ \hex@e@dx}{ \hex@e@dy}} \savedanchor{\northwestedge}{\pgfqpoint{-\hex@e@dx}{ \hex@e@dy}} \savedanchor{\southwestedge}{\pgfqpoint{-\hex@e@dx}{-\hex@e@dy}} \savedanchor{\southeastedge}{\pgfqpoint{ \hex@e@dx}{-\hex@e@dy}} \savedmacro\init{% \def\hexpath{% \pgfpathmoveto{\east}% \pgfpathlineto{\northeast}% \pgfpathlineto{\northwest}% \pgfpathlineto{\west}% \pgfpathlineto{\southwest}% \pgfpathlineto{\southeast}% \pgfpathclose} } % \end{macrocode} % % These are the actual user callable anchors. We make anchors for % each vertex and mid points on each edge. % % \begin{macrocode} %% \anchor{center}{ \pgfpointorigin} \anchor{east}{ \east} \anchor{west}{ \west} \anchor{north east}{ \northeast} \anchor{north west}{ \northwest} \anchor{south west}{ \southwest} \anchor{south east}{ \southeast} \anchor{north edge}{ \northedge} \anchor{south edge}{ \southedge} \anchor{north east edge}{\northeastedge} \anchor{north west edge}{\northwestedge} \anchor{south west edge}{\southwestedge} \anchor{south east edge}{\southeastedge} % \end{macrocode} % % Next we make some short hand aliases for each of these anchors. % % \begin{macrocode} \anchor{E}{ \east} \anchor{W}{ \west} \anchor{NE}{ \northeast} \anchor{NW}{ \northwest} \anchor{SW}{ \southwest} \anchor{SE}{ \southeast} \anchor{N edge}{ \northedge} \anchor{S edge}{ \southedge} \anchor{NE edge}{\northeastedge} \anchor{NW edge}{\northwestedge} \anchor{SW edge}{\southwestedge} \anchor{SE edge}{\southeastedge} % \end{macrocode} % % The next part is commented out because its not obvious we'll use % these. % % \begin{macrocode} %% \savedanchor{\chitnorth}{ \pgfqpoint{ 0cm}{ 0.6cm}} \savedanchor{\chitsouth}{ \pgfqpoint{ 0cm}{ -0.6cm}} \savedanchor{\chiteast}{ \pgfqpoint{ 0.6cm}{ 0cm}} \savedanchor{\chitwest}{ \pgfqpoint{-0.6cm}{ 0cm}} \savedanchor{\chitnortheast}{\pgfqpoint{ 0.6cm}{ 0.6cm}} \savedanchor{\chitnorthwest}{\pgfqpoint{-0.6cm}{ 0.6cm}} \savedanchor{\chitsouthwest}{\pgfqpoint{-0.6cm}{-0.6cm}} \savedanchor{\chitsoutheast}{\pgfqpoint{ 0.6cm}{-0.6cm}} % \anchor{chit north}{\chitnorth} \anchor{chit south}{\chitsouth} \anchor{chit east}{\chiteast} \anchor{chit west}{\chitwest} \anchor{chit north east}{\chitnortheast} \anchor{chit north west}{\chitnorthwest} \anchor{chit south west}{\chitsouthwest} \anchor{chit south east}{\chitsoutheast} % \anchor{chit N}{\chitnorth} \anchor{chit S}{\chitsouth} \anchor{chit E}{\chiteast} \anchor{chit W}{\chitwest} \anchor{chit NE}{\chitnortheast} \anchor{chit NW}{\chitnorthwest} \anchor{chit SW}{\chitsouthwest} \anchor{chit SE}{\chitsoutheast} % % \end{macrocode} % % The background path. This path may be drawn when the node is % drawn. However, we will do most of the work in the % \cs{behindbackgroundpath} which gets drawn \emph{after} this path. % % \begin{macrocode} \backgroundpath{\init\hexpath} % \end{macrocode} % % The \emph{behind} background path, where we do most of the work. % % \begin{macrocode} \behindforegroundpath{% \hex@dbg{2}{Hex behind foreground path: ^^JTerrain: `\meaning\hex@terrain' ^^JRidges: `\meaning\hex@ridges' ^^JTown: `\meaning\hex@town' ^^JExtra clipped: `\meaning\hex@extra@clip' ^^JLabel: `\meaning\hex@label' ^^JExtra: `\meaning\hex@extra' ^^JLast node name:`\meaning\tikzlastnode' ^^JHex row: `\meaning\hex@row' ^^JHex col: `\meaning\hex@col' }% \init% % \end{macrocode} % % We start a scope and clip to the hex path first. % % \begin{macrocode} \scope% \hexpath% \pgfusepath{clip}% % \end{macrocode} % % Anything inside this scope is clipped to the hex path. The next % step is to see if we have a specified terrain for the hex. % % \begin{macrocode} \@ifundefined{hex@terrain}{\let\hex@terrain\empty}{}% \ifx\hex@terrain\empty\else\hex@do@terrain\fi% % \end{macrocode} % % This concludes the processing of the terrain of the hex. Next, we % must see if the user specified ridges. % % \begin{macrocode} \@ifundefined{hex@ridges}{\let\hex@ridges\empty}{}% \ifx\hex@ridges\empty\else\hex@do@ridges\fi% % \end{macrocode} % % This concludes the processing of the ridges of the hex. Next, we % should process any extra (clipped) stuff specified. The user may % pass options to each \spec{pic}ture by preceding it with % \oarg{options}. % % \begin{macrocode} \@ifundefined{hex@extra@clip}{\let\hex@extra@clip\empty}{} \ifx\hex@extra@clip\empty\else% \hex@dbg{5}{Extra clipped: `\meaning\hex@extra'} \pgfpointorigin\wg@tmpa=\pgf@x\wg@tmpb=\pgf@y% \wg@pic@all{\hex@extra@clip}{}{\the\wg@tmpa,\the\wg@tmpb}{}% \fi% % \end{macrocode} % % This concludes the extra stuff put in the hex. Next, we should % place the label is specified. Note, we may know the hex row and % column at this point, stored in \cs{hex@row} and \cs{hex@column}, % respectively. We may want to name the generated node from these if % the user specified that option (perhaps use \cs{pgfnoderename} or % similar). % % \begin{macrocode} \@ifundefined{hex@label}{\let\hex@label\empty}{} \ifx\hex@label\empty\else\hex@do@label\fi% % \end{macrocode} % % \begin{macrocode} \@ifundefined{hex@bevel}{\let\hex@bevel\empty}{} \ifx\hex@bevel\empty\else% \northeast \wg@tmpa=\pgf@x\wg@tmpb=\pgf@y% \west \wg@tmpc=\pgf@x\wg@tmpd=\pgf@y% \ifcase\hex@bevel\relax \or%1 \or\wg@tmpa=-\wg@tmpa\wg@tmpc=-\wg@tmpc%2 \or\wg@tmpb=-\wg@tmpb\wg@tmpd=-\wg@tmpd%3 \or% 4 \wg@tmpa=-\wg@tmpa\wg@tmpc=-\wg@tmpc% \wg@tmpb=-\wg@tmpb\wg@tmpd=-\wg@tmpd% \fi \hex@bevel@path{chit/bevel highlight} \northeast \wg@tmpa=-\pgf@x\wg@tmpb=-\pgf@y% \west \wg@tmpc=-\pgf@x\wg@tmpd=-\pgf@y% \ifcase\hex@bevel\relax \or%1 \or\wg@tmpa=-\wg@tmpa\wg@tmpc=-\wg@tmpc%2 \or\wg@tmpb=-\wg@tmpb\wg@tmpd=-\wg@tmpd%3 \or% 4 \wg@tmpa=-\wg@tmpa\wg@tmpc=-\wg@tmpc% \wg@tmpb=-\wg@tmpb\wg@tmpd=-\wg@tmpd% \fi \hex@bevel@path{chit/bevel shadow} \fi % \end{macrocode} % \begin{macrocode} \endscope% % \end{macrocode} % % This concludes the label processing, and stuff that should be % clipped to the hex shape. If the user specified a town, we can now % make that. % % \begin{macrocode} \@ifundefined{hex@town}{\let\hex@town\empty}{} \@ifundefined{hex@c@pic}{\let\hex@c@pic\empty}{} \ifx\hex@town\empty\else\hex@do@town\fi% % \end{macrocode} % % We can now add extra (non-clipped) stuff. We assume that extra % stuff is \spec{pic}tures. The user may pass options to each % \spec{pic}ture by preceding it with \oarg{options}. % % \begin{macrocode} \@ifundefined{hex@extra}{\let\hex@extra\empty}{} \ifx\hex@extra\empty\else% \hex@dbg{5}{Extra: `\meaning\hex@extra'} \pgfpointorigin\wg@tmpa=\pgf@x\wg@tmpb=\pgf@y% \wg@pic@all{\hex@extra}{}{\the\wg@tmpa,\the\wg@tmpb}{}% \fi% } } % \end{macrocode} % % \begin{HexKey*}{ % /hex/terrain, % /hex/town, % /hex/label, % /hex/ridges, % /hex/extra, % /hex/extra clipped} % % Next, we set up the name space for hex keys. This is the top level % name space for hexes. Sub keys \spec{terrain}, \spec{ridges}, % \spec{town}, \spec{extra}, \spec{label}, and \spec{extra clipped}, % store their arguments in macros and we expand these later on. This % allows us to scope some of the keys given to those specific parts. % % Define keys for hexagon options. These are % % \begin{tabular}{|l|p{.7\linewidth}|} % \hline % \rowcolor{headbg} % {\color{headfg}\textbf{Name}} % & {\color{headfg}\textbf{Description}}\\ % \hline % \spec{terrain} & Terrain\\ % \spec{label} & Label on hex\\ % \spec{town} & Town in hex. Optionally with a name\\ % \spec{ridges} & Ridge markings on hex\\ % \spec{extra} & More \\ % \spec{extra clipped} & More clipped to hex\\ % \hline % \end{tabular} % % \begin{macrocode} \tikzset{% /hex/.search also={/tikz},% /hex/.cd,% terrain/.store in=\hex@terrain,% ridges/.store in=\hex@ridges,% town/.store in=\hex@town,% extra/.store in=\hex@extra,% label/.store in=\hex@label,% extra clipped/.store in=\hex@extra@clip% } % \end{macrocode} % \end{HexKey*} % % \begin{TikzKey}{hex} % The next key is the real work horse of the show. Specifying the % \spec{hex} key to a node effectively creates a hex for us. Now, % there are some things we cannot do outright in the node shape % code. For example, we cannot set the name of the node created % from the shape code. Therefore, the use of \cs{hex} is often the % right choice. % % \begin{macrocode} \tikzset{% hex/hex/.style={ transform shape, anchor=center, draw=pgfstrokecolor, fill=none, thick, solid}, hex/.code={% \hex@dbg{1}{=== Hex with options: `#1'}% \pgfkeys{/tikz/transform shape,/tikz/shape=hex/hex} \pgfkeys{/hex/.cd,/tikz/hex/hex,/tikz/every hex/.try,#1}}} % \end{macrocode} % \end{TikzKey} % % The first thing is to set the default graphics options. The key % \spec{every hex} can be set to hex options to be used for all hexes. % For example, if one want to label all hexes with an auto-generated % label, one can do % % \begin{Syntax} % \cs{tikzset}\{every hex/.style=\{label=\{auto=numbered\}\}\} % \end{Syntax} % % This, coupled with the \spec{hex/label is name} option allows us to % set up the board with really minimal effort. We can then use the % board coordinates when placing units, and other things. % % % Now we have set up these tools we can go on and define the user % facing macro. % % \begin{Macro}{\hex,\hex@,\hex@@} % % This will add a hex to the output graphics. Note, the macro % need not be followed by a semi-colon (\spec{;}). % % First argument is optional options. % % \begin{macrocode} \def\hex{% \@ifnextchar[{\hex@}{\hex@[]}%] } % \end{macrocode} % % Second optional argument is the coordinates. These should be given % in the hex coordinate system. % % \begin{macrocode} \def\hex@[#1]{% \@ifnextchar({\hex@@{#1}}{% \hex@@{#1}(c=0,r=0)}%) } % \end{macrocode} % % Third argument is the name to be used. % % \begin{macrocode} \def\hex@@#1(#2){% \@ifnextchar({\hex@@@{#1}{#2}}{\hex@@@{#1}{#2}()}%) } % \end{macrocode} % % Now for the real work-horse. First thing is to reset keys and parse % them out from the arguments. % % \begin{macrocode} % Third argument is name \def\hex@@@#1#2(#3){% \node[hex={#1}] (tmp) at (hex cs:#2) {};% \hex@dbg{8}{=== Label text: `\meaning\hex@l@text'} \ifx|#3|\relax% \@ifundefined{hex@l@text}{% \hex@dbg{8}{=== Label text of hex (#2) not defined}% \let\hex@l@text\empty% }{} \ifhex@label@is@name% \hex@dbg{5}{=== Use label text of hex (#2) as name}% \ifx\hex@l@text\@empty% \hex@dbg{8}{=== Argh! Label text is empty! `\meaning\hex@l@text'} \else% \hex@dbg{3}{=== Renaming hex to label text `\hex@l@text'} \pgfnoderename{\hex@l@text}{tmp}% \fi% \fi% \else% \hex@dbg{3}{=== Renaming hex to user defined name `#3'}% \pgfnoderename{#3}{tmp}% \fi% \@ifnextchar;{\@gobble}{}% } % \end{macrocode} % \end{Macro} % \iffalse % % -------------------------------------------------------------------- % \fi