summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/wargame/source/hex/shape.dtx
blob: 0d31da837fb442d2148b92acbb07bdaac3685590 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
% \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}
\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%
    \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
%</hex>
% --------------------------------------------------------------------
% \fi