summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/scalebar/scalebar.dtx
blob: 7977dd67b30b9540d6328da8e79473d7639ece35 (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
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
% \iffalse meta-comment
%
% This is the scalebar package, scalebar.dtx
%
% Copyright (C) 2003 by Michael Lake <mikel@speleonics.com.au>
%
% This file may be distributed and/or modified under the conditions of
% the LaTeX Project Public License, either version 1.2 of this license
% or (at your option) any later version.  The latest version of this
% license is in:
% 
%    http://www.latex-project.org/lppl.txt
% 
% and version 1.2 or later is part of all distributions of 
% LaTeX version 1999/12/01 or later.
%
%
%<*driver>
\ProvidesFile{scalebar.dtx}
%</driver>
%
%
%<package>\ProvidesPackage{scalebar}%
           [2003/05/01 v1.0 Scalebars for maps and diagrams] 
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\RequirePackage{ifthen}
%<package>\RequirePackage{calc}
%<package>\RequirePackage{fp}
%
%<*driver>
\documentclass{ltxdoc}
\GetFileInfo{scalebar.dtx}
\EnableCrossrefs         
\CodelineIndex
\RecordChanges
%\OnlyDescription
\begin{document}
  \DocInput{scalebar.dtx}
\end{document}
%</driver>
%
% \fi
%
% \CheckSum{187}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
% \changes{v1.0}{2003/05/01}{Initial version}
%
% \DoNotIndex{
% \newcounter,\setcounter,\addtocounter,\newlength,\setlength,
% \else,\fi,\hfill,\hspace,\rule,\newcommand}
%
% \setlength{\parskip}{0.4\baselineskip}
% \setlength{\parindent}{0pt}
%
% \title{The \textsf{scalebar} package}
% \author{Michael Lake\\ \texttt{mikel@speleonics.com.au}}
% \date{\fileversion{} -- \filedate}
% \maketitle
% 
% 
%
% \section{Introduction}
%
% This document describes the \textsf{scalebar} package for \LaTeXe, which 
% creates scalebars for maps, diagrams or photos. 
% It was designed for use with cave maps, but
% can be used for anything from showing a scalebar in kilometers for 
% topographic maps to a scalebar in micrometers for 
% an electron microscope image.
%
% Here is an example scalebar. 
% See the scalebar\_examples file for further examples and possible uses.
% 
% ^^A In the scalebar below I have not used the \scalebar command
% ^^A as the user would not have it yet to typeset the scalebar so I
% ^^A have used two temporary commands to typeset some rules and created
% ^^A the scalebar from those.
% \newcommand{\tempA}[1]{\rule{#1}{2mm}\hspace{-#1}\raisebox{-2mm}{\rule{#1}{0.2mm}}}
% \newcommand{\tempB}[1]{\raisebox{1.8mm}{\rule{#1}{0.2mm}}\hspace{-#1}\raisebox{-2mm}{\rule{#1}{2mm}}}
% ^^A Now from the above two commands create a scalebar.
% \raisebox{-2mm}{\rule{0.2mm}{4mm}}\tempA{5mm}\tempB{5mm}\tempA{5mm}\tempB{5mm}\tempA{20mm}\tempB{20mm}\tempA{20mm}\tempB{20mm}\raisebox{-2mm}{\rule{0.2mm}{4mm}}
%
% ^^A Scale the text manually. Normally \scalebar would do this for you.
%\hspace{-0.5ex}0\hspace{1.85cm}2\hspace{1.8cm}4\hspace{1.85cm}6\hspace{1.8cm}8\hspace{1.75cm}10\,m
%
% \section{Usage}
%
%
% \DescribeMacro{\scalebar}
% The \textsf{scalebar} package defines one user command.
% To use the command you write;
%
% |\scalebar|\oarg{inverse}\marg{length}\marg{minordivs}\marg{majordivs}\\
% |                  |\marg{starting No.}\marg{ending No.}\marg{units}
%  
% \noindent where the six mandatory arguments are:
%
% \begin{tabular}{lp{9.5cm}}
% \meta{length}&the desired length of the scalebar on paper 
%               e.g.\ 10cm or 4in\\
% \meta{minordivs}&number of minor divisions within the first major 
%            division e.g.\ 4 (the first major division will always be 
%            subdivided unless this value is set to 1)\\
% \meta{majordivs}&number of major divisions e.g.\ 5 \\
% \meta{starting No.}&the number that the scalebar text will start from 
%       e.g.\ 0 or -0.5\\
% \meta{ending No.}&the number that the scalebar text will end with 
%       e.g.\ 2.5 or 25\\
% \meta{units}&the units for the scalebar text e.g.\ $\mu$m or km.
% \end{tabular}
% \vspace{0.4\baselineskip}
%
% The optional argument \meta{inverse} reverses the black and white regions.
% The default setting is for the top of the first bar to be black.
%
%
% \newpage 
% \section{Current Limitations and Future Enhancements}   
% \begin{description}  
% \item[Scalebar height/text ratio is hardcoded] 
% The height of the black rules in the scalebars is |1.2ex| so it scales
% with the current font height. This value seems about right but if you 
% want a different height compared to the text height you will have to modify
% the style file (modify |\SB@Height|). This could possibly be set as 
% an optional argument to the package.
% \item[Thickness of the thin rule is fixed] The thickness of the thin rule 
% is set to 0.2\,mm. This seems about right. If you wish to change it is easy 
% to modify the style file (|\SB@Thick|). 
% \item[Number of decimal places is limited to one] Scalebars rarely display
% more than one decimal place in the scalebar text. This package rounds the
% decimals of the displayed text to one place. If you want two decimal places
% you will have to modify the style file.
% \end{description}  
%
% Please let me know if you encounter any problems.
% If you have suggestions for extra options to add, then code for that 
% would be appeciated.
%
%
% \StopEventually{\PrintChanges \PrintIndex}
%
% \section{Implementation}
%
% First we have to decide how a scalebar is constructed.  Looking a a scalebar
% one can see that it is made up of alternating black and white bars. It would
% seem sensible therefore to define some sort of ``unit'' or ``building block''
% that can be iterated any number of times to create a scalebar of arbitary
% length and with an arbitary number of divisions.  The diagram below of a
% scalebar and its deconstruction shows one way to break it up into units. 
% \vspace{0.4\baselineskip}
%
% \raisebox{-2mm}{\rule{0.2mm}{4mm}}\tempA{5mm}\tempB{5mm}\tempA{5mm}\tempB{5mm}\tempA{20mm}\tempB{20mm}\tempA{20mm}\raisebox{-2mm}{\rule{0.2mm}{4mm}}
% \vspace{0.6\baselineskip}
%
% \raisebox{-2mm}{\rule{0.2mm}{4mm}} \mbox{} 
% \tempA{5mm} \mbox{} \tempB{5mm} \mbox{} \tempA{5mm} \mbox{} \tempB{5mm} \mbox{} 
% \tempA{20mm} \mbox{} \tempB{20mm} \mbox{} \tempA{20mm} \mbox{} \raisebox{-2mm}{\rule{0.2mm}{4mm}}
% \vspace{0.8\baselineskip}
%
% Looking at the parts above you can see there is a thin vertical rule at the
% start of each scalebar. This is followed by repeating ``scalebar units'' each
% one of which alternates in color. Finally there is a thin vertical rule to
% close the end of the scalebar.
%
% I have therefore defined two scalebar units. The first one typesets the thick
% black rule on the top.  After writing this rule we then move back
% horizontally a distance equal to the width of the rule written. Then we write
% the thinner rule underneath it by using a raisebox with a negative vertical
% distance. This unit looks like this:
%
% \hspace{2em}\tempA{5mm}\ X%
% \hspace{2em}(the X shows the position of the baseline)
% \vspace{0.2\baselineskip}
%
% The second type of unit has the thick black rule on the bottom like this:
%
% \hspace{2em}\tempB{5mm}\ X
% \vspace{0.2\baselineskip}
%
% By stringing these two types of units together within a while loop 
% we can create our scalebars.
% Let's now proceed to the start of the macro. 
% 
% \subsection{Required Packages}
%
% We have used the \textsf{fp} package to provide floating point calculations
% and a rounding function via the |\FPupn| macro. The \textsf{calc} package 
% provides an easy calculation syntax for simple subtraction of lengths.
% The \textsf{ifthen} package provides the whiledo loop and the 
% ifthenelse contruct.
%
% \subsection{Initialisation}
% 
% Note that we have to place a \% at the end of each command to suppress any 
% whitespace. Otherwise the scalebar will ``break apart''.
%
% \begin{macro}{counters/lengths} 
%
% Define counters and lengths. 
%
% The first three mandatory arguments specify the length of the scalebar and
% the numbers of the divisions. The arguments that specify the format of text
% underneath the scalebar will be introduced later. 
% 
%    \begin{macrocode}
\newlength{\SB@Length}%
\newcounter{SB@majordivs}%
\newcounter{SB@minordivs}%
%    \end{macrocode}
%
% These are some further general counters and lengths.
%
%    \begin{macrocode}
\newcounter{SB@evenodd}%
\newcounter{SB@countup}%
\newlength{\SB@Height}%
\newlength{\SB@Thick}%
\newlength{\SB@MajorWidth}%
\newlength{\SB@MinorWidth}%
\newlength{\SB@DivisionWidth}%
\newlength{\SB@TextWidth}%
%    \end{macrocode}
% \end{macro}
%
%
% Now define two small commands to typeset the two `scalebar units'. 
%
% \begin{macro}{\SB@unitT}
%
% This command typesets the unit with the thick black rule on the \emph{top}.
%
%    \begin{macrocode}
\newcommand{\SB@unitT}{%
\rule{\SB@DivisionWidth}{\SB@Height}\hspace{-\SB@DivisionWidth}%
\raisebox{-\SB@Height}{\rule{\SB@DivisionWidth}{\SB@Thick}}}%
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\SB@unitB}
%
% This command typesets the thick black rule on the \emph{bottom}.
%
%    \begin{macrocode}
\newcommand{\SB@unitB}{%
\raisebox{\SB@Height-\SB@Thick}%
{\rule{\SB@DivisionWidth}{\SB@Thick}}\hspace{-\SB@DivisionWidth}%
\raisebox{-\SB@Height}{\rule{\SB@DivisionWidth}{\SB@Height}}}%
%    \end{macrocode}
% \end{macro}
%
%
% \newpage
% \subsection{The scalebar macro}
%
% \begin{macro}{\scalebar}
% Start the scalebar command and process the command arguments. 
%
% \begin{macro}{args}
% The first argument is an optional argument which is set to 
% nothing as default. Normally the value 
% of |SB@evenodd| is 0 which will result in the black rule of 
% the first division being on top. If \meta{inverse} is set the
% black rule will be set on the bottom.
%
%    \begin{macrocode}
\newcommand{\scalebar}[7][]{%
%
\ifthenelse{\equal{inverse}{#1}}%
{\setcounter{SB@evenodd}{1}}%
{\setcounter{SB@evenodd}{0}}%
%    \end{macrocode}
%
% Read in the next three mandatory arguments.
%
%    \begin{macrocode}
\setlength{\SB@Length}{#2}%
\setcounter{SB@minordivs}{#3}%
\setcounter{SB@majordivs}{#4}%
%    \end{macrocode}
%
% Define the number at which the text will start by |\SB@StartNo|; 
% the number at which it will end by |\SB@EndNo| and the units the text 
% represents by |\SB@TextUnits|. These are set to the last three mandatory 
% arguments.  
%
%    \begin{macrocode}
\def\SB@StartNo{#5}%
\def\SB@EndNo{#6}%
\def\SB@TextUnits{#7}%
%    \end{macrocode}
% \end{macro}
%
%
% Set the height of the scalebar and thickness of the thin enclosing rule.
%
% Let the height of the thick black rule of a division be |\SB@Height| and set
% it to a value related to the x-height of the current font.  This is because
% we want the scalebar to increase in height if the user specifies a change in
% font size.  It's set after the command begins rather than earlier as we want
% it to pickup a font change immediately before the scalebar command if any.
% The thin rule that encloses the divisions (|\SB@Thick|) will be hard coded to
% 0.2\,mm. This was chosen as it looked about right :-)
%
%    \begin{macrocode}
\setlength{\SB@Height}{1.2ex}%
\setlength{\SB@Thick}{0.2mm}%
%    \end{macrocode}
%
%
% Calculate the lengths of the divisions. 
%
% Let's define |\SB@MajorWidth| to be the width (i.e.\ length) of a 
% major division.
% To calculate this we take the total scalebar length and divide by
% the number of major divisions.
% To calculate the length of a minor division, |\SB@MinorWidth|, we divide
% the major division length just calculated by the number of minor divisions.
%
%    \begin{macrocode}
\setlength{\SB@MajorWidth}{\SB@Length / \theSB@majordivs}%
\setlength{\SB@MinorWidth}{\SB@MajorWidth / \theSB@minordivs}%
%    \end{macrocode}
%
%
%
% \subsection{Drawing the scalebar}
%
% Now we can start placing ink to paper. 
% Place onto the page the thin vertical rule at the start of the scalebar.
% As it starts at the baseline we have to make it twice the height of 
% |\SB@Height| and lower it by |\SB@Height|.
%
%    \begin{macrocode}
\raisebox{-\SB@Height}{\rule{\SB@Thick}{2\SB@Height}}%
%    \end{macrocode}
%
%
% Use a while loop to place the minor divisions onto the page.  (Use a new
% counter rather than decrementing minordivs variable.) Note
% that we alternate between using the |\SB@unitT| or the |\SB@unitB| unit
% depending on the value of the |SB@evenodd| variable.  That value
% is set at the beginning and depends on the setting of the optional
% \meta{inverse} argument.
%
%    \begin{macrocode}
\setlength{\SB@DivisionWidth}{\SB@MinorWidth}% 
\setcounter{SB@countup}{0}%
\whiledo{\not\theSB@countup=\theSB@minordivs}{%
\ifthenelse{\isodd{\value{SB@evenodd}}}{\SB@unitB}{\SB@unitT}%
\addtocounter{SB@evenodd}{1}%
\addtocounter{SB@countup}{1}}%
%    \end{macrocode}
%
%
% Now that the minor divisions are done we can write the major divisions. 
%
% Note that we have to reset the length of the rule from the 
% current width of a minor division to the width of a major division.
% Set the counter this time to start at 1 rather than 0 
% as we have already written all the minor divisions which adds up 
% to one major division.
%
%    \begin{macrocode}
\setlength{\SB@DivisionWidth}{\SB@MajorWidth}% 
\setcounter{SB@countup}{1}%
\whiledo{\not\theSB@countup=\theSB@majordivs}{%
\ifthenelse{\isodd{\value{SB@evenodd}}}{\SB@unitB}{\SB@unitT}%
\addtocounter{SB@evenodd}{1}%
\addtocounter{SB@countup}{1}}%
%    \end{macrocode}
%
% Finally we have to print the thin vertical rule at the end. 
%
%    \begin{macrocode}
\raisebox{-\SB@Height}{\rule{\SB@Thick}{2\SB@Height}}%
%    \end{macrocode}
%
%
% \subsection{Typesetting the scalebar numbers}
%
% Typesetting of the text underneath the scalebar requires three
% pieces of information; the number at which the text will start, 
% the number at which it will end and what units the text represents.
% The numbering does not have to start at zero.
%
% Some scalebars will consist of integers only as in the text below.\\
% 0\hspace{1.5cm}2\hspace{1.5cm}4\hspace{1.5cm}6\hspace{1.5cm}8\hspace{1.5cm}10\,km
% 
% Other scalebars will have decimals. Althought usually scalebars only show 
% one decimal place at most. \\
% -0.5\hspace{1.5cm}0\hspace{1.5cm}1.5\hspace{1.5cm}2.0\hspace{1.5cm}2.5\,cm
%
%
% We now use macros provided by the fp.sty (fixed point)
% package to perform some simple arithmetic and rounding. 
%
% Calculate how much we will increment the numbers by subtracting 
% the starting and ending numbers (|SB@StartNo| and |SB@EndNo|) then dividing their difference by the 
% number of major divisions. 
%
%    \begin{macrocode}
\FPupn\SBIncrement%
{\the\value{SB@majordivs} \SB@StartNo{} \SB@EndNo{} - /}%
%    \end{macrocode}
%
%
% Now we need to work out how many decimal places to display for the numbers.
%
% Start off with rounding set to none. If the calculated increment 
% is an integer then don't do anything, otherwise set rounding on and 
% round the increment to one decimal place. This would suffice for many 
% variations of starting and ending number, however if the user entered
% -0.5 to 2.5 for these values respectively then the increment (3.0) would be 
% an integer and the rounding would be set to zero. In theses cases though
% the starting and ending numbers must be non-integer thus by testing all three
% numbers we can cover all cases.
%
%    \begin{macrocode}
\def\SBRound{0}%
\FPifint\SBIncrement%
\else\def\SBRound{1}\FPupn\SBIncrement{\SBIncrement{} 1 round}\fi%
\FPifint\SB@StartNo%
\else\def\SBRound{1}\FPupn\SB@StartNo{\SB@StartNo{} 1 round}\fi%
\FPifint\SB@EndNo%
\else\def\SBRound{1}\FPupn\SB@EndNo{\SB@EndNo{} 1 round}\fi%
%    \end{macrocode}
%
%
% Now remember that we are at the end of the scalebar so to print the
% text underneath we have to move back to the left and down.
% Move left by a distance equal to the scalebar length (|\SB@Length|) 
% plus a little bit more to take into account the thickness of the thin 
% line at the start and end of the scalebar (|\SB@Thick|). 
% Then move down by enough to place the
% text at a nice distance below the scalebar. Remember that the distance
% |\SB@Height| depends on the current font in a fixed ratio set earlier.
%
%    \begin{macrocode}
\hspace{-\SB@Length}\hspace{-\SB@Thick}%
\raisebox{-3\SB@Height}{%
%    \end{macrocode}
%
% Now we are ready to print the numbers.
% The length |\SB@TextWidth| contains the
% width of the text that we are about to put to page. 
% We need to calculate this so that we can fine position the center of 
% the text to be exactly under the start of each major division.
% Note how we use the value of |\SBRound| to set the number of 
% decimal places in the text we typeset.
%
%    \begin{macrocode}
\FPset\SBNextNo\SB@StartNo%
\setcounter{SB@countup}{0}%
\whiledo{\not\theSB@countup>\theSB@majordivs}{%
\FPupn\SBNextNo{\SBNextNo{} \SBRound{} round}%
\settowidth{\SB@TextWidth}{\SBNextNo}%
\hspace{-0.5\SB@TextWidth}%
\SBNextNo\hspace{-0.5\SB@TextWidth}\hspace{\SB@MajorWidth}%
\FPupn\SBNextNo{\SBNextNo{} \SBIncrement{} add}%
\addtocounter{SB@countup}{1}}%
%    \end{macrocode}
%
% Now all the numbers are on the page we are nearly ready to append 
% the scalebars units to the end. First though we have to move back 
% by the distance |\SB@MajorWidth| as the last while loop added 
% this unwanted space, then forward half of the width of the last 
% number printed. 
% Finally add a thin space and the units and finish the scalebar 
% command with its closing brace.
%
%    \begin{macrocode}
\hspace{-\SB@MajorWidth}\hspace{0.5\SB@TextWidth}\,\SB@TextUnits}%
}%
%    \end{macrocode}
% \end{macro}
%
% That's the end of the macro.
%
% \section*{License}\label{sec:license}
% This program may be distributed and/or modified under the
% conditions of the \LaTeX\ Project Public License, either version 1.2
% of this license or (at your option) any later version.
% The latest version of this license is in
%
% \hspace{2em}http://www.latex-project.org/lppl.txt
%
% and version 1.2 or later is part of all distributions of \LaTeX \
% version 1999/12/01 or later.
%
% This program consists of the files \textsf{scalebar.dtx} and
% \textsf{scalebar.ins}
%
%
% \section*{Acknowledgements}
%
% Thanks to the people on the \textsf{comp.text.tex} newsgroup for their 
% help to me in developing this package. 
%
%
% \Finale{\vspace{\baselineskip}\hfill\rule{3in}{0.1pt}\hfill}
\endinput