% \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
