summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/smartunits/smartunits.tex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/smartunits/smartunits.tex')
-rw-r--r--macros/latex/contrib/smartunits/smartunits.tex427
1 files changed, 427 insertions, 0 deletions
diff --git a/macros/latex/contrib/smartunits/smartunits.tex b/macros/latex/contrib/smartunits/smartunits.tex
new file mode 100644
index 0000000000..fe57502fbd
--- /dev/null
+++ b/macros/latex/contrib/smartunits/smartunits.tex
@@ -0,0 +1,427 @@
+\documentclass[svgnames]{report}
+\usepackage{smartunits}
+\usepackage{manfnt}
+\usepackage{enumitem}
+\setlist[description]{font=\sffamily\bfseries\color{DodgerBlue},labelwidth=\textwidth}
+\usepackage{booktabs}
+\usepackage[a4paper,margin=18mm]{geometry}
+\synctex=1
+
+\usepackage{fixltx2e} % LaTeX patches, \textsubscript
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\setcounter{secnumdepth}{0}
+
+\usepackage{listings}\lstset{language=[LaTeX]TeX,framerule=2pt}
+\lstset{language=[LaTeX]TeX,
+ texcsstyle=*\bfseries\color{Blue},
+ backgroundcolor=\color{Ivory},
+ numbers=none,
+ breaklines=true,
+ keywordstyle=\color{Blue},
+ commentstyle=\color{Brown},
+ tabsize=2,
+ morekeywords={SmartUnit,SmartUnitSettings,sisetup},
+ resetmargins=true,
+}
+% hyperref links to ctan
+\newcommand\ctan[1]{\href{https://www.ctan.org/pkg/#1}{\texttt{#1}}}
+
+\usepackage{xparse}
+\NewDocumentCommand{\Verb}{v}{{\color{blue}#1}}
+
+\newcommand\Section[1]{\subsection{\textcolor{blue}{#1}}}
+
+\makeatletter
+\author{Andrew Mathas}
+\usepackage{tikz}
+\usetikzlibrary{shadows.blur}
+\tikzset{shadowed/.style={blur shadow={shadow blur steps=5},
+ bottom color=LightSkyBlue!30,
+ draw=MidnightBlue!70,shade,
+ font=\normalfont\Huge\bfseries\scshape,
+ rounded corners=8pt,
+ top color=SkyBlue,
+ },
+ boxes/.style={draw=MidnightBlue,
+ fill=Cornsilk,
+ font=\sffamily\small,
+ inner sep=5pt,
+ rectangle,
+ rounded corners=8pt,
+ text=RoyalBlue,
+ }
+}
+\def\SmartTitle{
+ \begin{tikzpicture}[remember picture,overlay]
+ \node[yshift=-3cm] at (current page.north west)
+ {\begin{tikzpicture}[remember picture, overlay]
+ \draw[shadowed](30mm,0) rectangle node[white]{Smart Units} (\paperwidth-30mm,16mm);
+ \node[anchor=west,boxes] at (4cm,0cm) {\@author};
+ \node[anchor=east,boxes] at (\paperwidth-4cm,0) {\smart@version};
+ \end{tikzpicture}
+ };
+ \end{tikzpicture}
+ \vspace*{20mm}
+}
+
+
+\def\@oddfoot{\textsc{Smart Units} -- \smart@version\hfill\thepage}
+
+\usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+\hypersetup{pdfcreator={ Generated by pdfLaTeX },
+ pdfinfo={Author ={ Andrew Mathas },
+ Keywords={ units, metric, Imperial },
+ License ={ LaTeX Project Public License v1.3c or later },
+ Subject ={ Convert between metric and Imperial units },
+ Title ={ smartunits - \smart@version }
+ },
+}
+\makeatother
+
+\begin{document}
+
+ \SmartTitle
+
+ %\Section{Smart units}
+ This package implements a \Verb|\SmartUnit| macro for
+ converting between the following metric and Imperial units:
+
+ \begin{center}
+ \begin{tabular}{@{\color{Grey!50}}ll@{\quad$\longleftrightarrow$\quad}l}\toprule
+ & Metric & Imperial \\\midrule
+ \color{LightSkyBlue}distance & kilometers & miles \\
+ \color{LightSkyBlue}length & centimeters & feet and inches \\
+ \color{LightSkyBlue}temperature & Celsius & Fahrenheit \\
+ \color{LightSkyBlue}time & 24-hour time& 12-hour time \\
+ \color{LightSkyBlue}volume & litres & USA/UK gallons \\
+ \color{LightSkyBlue}weight & kilograms & pounds \\
+ \bottomrule
+ \end{tabular}
+ \end{center}
+ Of course, the underlying unit for length and distance is the same
+ but it makes sense to convert between units of similar ``scale''.
+ The \Verb|\SmartUnit| macro is designed to print only one unit at a
+ time, where the quantity is given in terms of either metric or
+ Imperial units (there is no error checking, however). Depending on
+ the (global) settings the unit will be printed either as a metric
+ unit, or as an Imperial unit, or both. If the required unit is not
+ given as an argument to \Verb|\SmartUnit| then it is computed.
+
+ The units are printed using \ctan{siunitx}, so the formatting of the
+ units can be controlled using \Verb|\sisetup| together with
+ formatting parameters from \ctan{siunitx}. Some aspects of the
+ formatting can be controlled ``locally'' using \Verb|\SmartUnit| and
+ ``globally'' using \Verb|\SmartUnitSettings|.
+
+ The \Verb|\SmartUnit| macro can print units in the following
+ four different formats:
+
+ \begin{lstlisting}
+ \SmartUnit{metric} % --> metric
+ \SmartUnit{imperial} % --> Imperial
+ \SmartUnit{metric imperial} % --> metric (Imperial)
+ \SmartUnit{imperial metric} % --> Imperial (metric)
+ \end{lstlisting}
+
+ For the impatient, here are some examples:
+
+ \bgroup
+ \sisetup{round-mode=places,round-precision=2}
+ \small
+ \begin{lstlisting}[escapeinside=<>]
+ \documentclass{article}
+ \usepackage{smartunits}
+ \begin{document}
+ \SmartUnitSettings{places=2} % Some global settings < \SmartUnitSettings{places=2} >
+ \SmartUnit{metric imperial} % Output format: metric (Imperial) < \SmartUnit{metric imperial} >
+ \SmartUnit{cm=10} % < \SmartUnit{cm=10} >
+ \SmartUnit{cm=66} % < \SmartUnit{cm=66} >
+ \SmartUnit{feet=4,inches=3} % < \SmartUnit{feet=4,inches=3} >
+ \SmartUnit{celsius=20} % < \SmartUnit{celsius=20} >
+ \SmartUnit{metric} % Output format: metric < \SmartUnit{metric} >
+ \SmartUnit{miles=5, places=1} % < \SmartUnit{miles=5,places=1} >
+ \SmartUnit{imperial} % Output format: Imperial < \SmartUnit{imperial} >
+ \SmartUnit{hours=12, minutes=1} % < \SmartUnit{hours=12, minutes=1} >
+ \SmartUnit{km=5,places=3} % < \SmartUnit{km=5,places=3} >
+ \SmartUnit{imperial metric} % Output format: Imperial (metric) < \SmartUnit{imperial metric} >
+ \SmartUnit{miles=5, km=7} % < \SmartUnit{miles=5,km=7} >
+ \SmartUnit{l=1.0, places=1} % < \SmartUnit{l=1.0, places=1} >
+ \SmartUnit{L=1.0, places=1} % < \SmartUnit{L=1.0, places=1} >
+ \SmartUnit{gal=25.0,uk,places=2} % < \SmartUnit{gal=25.0, places=2,uk} >
+ \SmartUnit{gal=25.0,usa,places=2} % < \SmartUnit{gal=25.0, places=2,usa} >
+ \end{document}
+ \end{lstlisting}
+ \egroup
+
+ The calculations done by \Verb|\SmartUnit| are reasonably accurate
+ but LaTeX is not a calculator so rounding and other errors can and
+ do happen (indeed, see the displayed example below). In addition, even assuming
+ that the calculations done by \Verb|\SmartUnit| are accurate this
+ may not be what you want. For example, if the metric unit is given
+ as \SI{100}{km} then many people will want the Imperial unit to be
+ written as \SI{60}{\text{mi}}, rather than the more accurate
+ \SI{62.137119}{\text{mi}}. In fact, \Verb|\SmartUnit| can cater for
+ these considerations because all units are printed using the
+ \ctan{siunitx} package, which is really clever. The precision of the
+ printed units can be controlled using \Verb|\sisetup|, from the
+ \ctan{siunitx} package or by using the short-hands, \textsf{figures}
+ and \textsf{places}, provided by \Verb|\SmartUnit|:
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=100.0, figures=1} % \SmartUnit{km=100.0,figures=1}
+ \SmartUnit{km=100.0, places=5} % \SmartUnit{km=100.0,places=5}
+ \end{lstlisting}
+ \noindent (Comparing with the paragraph above, the last calculation
+ is only accurate to three decimal places!) The values of the
+ computed units can be overridden, during proof-reading for example,
+ by specifying both the metric and Imperial units:
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=100,miles=70} % \SmartUnit{km=100,miles=70}
+ \end{lstlisting}
+ \noindent \raisebox{3.9mm}{\dbend}\quad Of course, if you specify
+ units incorrectly like this then incorrect values will be printed.
+
+ Behind the scenes all units are printed using \ctan{siunitx}. Therefore,
+ the precision and formatting of the units can be changed using the
+ options to \Verb|\sisetup| described in the \ctan{siunitx}\ manual. In
+ particular, when the rounding capabilities of~\ctan{siunitx}\ are enabled
+ any units calculated by \Verb|\SmartUnit| will be rounded.
+ In this case there is a shorthand for overriding the global
+ \ctan{siunitx}\ settings for the rounding precision on an individual
+ ``smart unit'':
+
+ \begin{lstlisting}[escapeinside=<>]
+ % Locally=\sisetup{round-precision=3, round-mode=places}
+ \SmartUnit{cm=2, places=3} % < \SmartUnit{cm=2, places=3} >
+ \end{lstlisting}
+
+ Section~5.5 of the \ctan{siunitx}\ manual should be consulted for all of the
+ options for controlling ``post-processing'' of numbers. In particular,
+ units that are given as integers will always be printed as integers.
+ For example, the metric version of \Verb|\SmartUnit{cm=2, places=3}|
+ is printed as \SmartUnit{cm=2, places=3, metric} whereas the Imperial version is
+ \num{0.787}$'$. If, instead, we use
+ \Verb|\SmartUnit{cm=2.0, places=3}| then the metric unit is
+ printed as \SmartUnit{cm=2.0, places=3, metric}.
+
+
+ \Section{Unit conversions}
+ For all of these examples we use the following global settings:
+ \begin{lstlisting}[texcl]
+ \SmartUnitSettings{places=2, metric imperial} % Global settings
+ \end{lstlisting}
+ \SmartUnitSettings{places=2, metric imperial}
+ \noindent Of course, as in some of the example below, this can always be overridden locally.
+
+ \begin{description}
+ \item[Distance -- km, miles, mi]
+ Conversions between kilometers and miles. Miles can be specified
+ using either \textbf{miles} or \textbf{mi}.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=100,miles=60} % \SmartUnit{km=100,miles=60}
+ \SmartUnit{km=100.0,figures=1} % \SmartUnit{km=100,figures=1}
+ \SmartUnit{miles=62.15,places=1} % \SmartUnit{miles=62.15,places=1}
+ \end{lstlisting}
+
+ \item[Length -- cm, inches, feet]
+ Feet are always printed as integers. Significant figures/places
+ are applied only to the printing of inches.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{feet=7, inches=1} % \SmartUnit{feet=7, inches=1}
+ \SmartUnit{cm=189, feet=7, inches=1} % \SmartUnit{cm=189, feet=7, inches=1}
+ \SmartUnit{cm=191, places=1} % \SmartUnit{cm=191, places=1}
+ \end{lstlisting}
+
+ \item[Temperature -- celsius, fahrenheit]
+ Convesions between Celsius and Fehrenheit can be speficied using
+ \textsf{celsius}, \textsf{C}, \textsf{fahrenheit} or \textsf{F}.
+
+ \begin{lstlisting}[texcl]
+ \SmartUnit{celsius=32,places=3} % \SmartUnit{celsius=32,places=3}
+ \SmartUnit{celsius=0} % \SmartUnit{celsius=0}
+ \SmartUnit{C=37} % \SmartUnit{C=37}
+ \SmartUnit{fahrenheit=0} % \SmartUnit{fahrenheit=0,places=2}
+ \SmartUnit{F=22,figures=4} % \SmartUnit{F=212,figures=4}
+ \end{lstlisting}
+
+ \item[Time -- hours, minutes, seconds, am, pm]
+ \begin{lstlisting}[texcl]
+ \SmartUnit{hours=0, minutes=59} % \SmartUnit{hours=0, minutes=59}
+ \SmartUnit{hours=12, minutes=12} % \SmartUnit{hours=12, minutes=12}
+ \SmartUnit{hours=13, minutes=9} % \SmartUnit{hours=13, minutes=9}
+ \SmartUnit{hours=8, minutes=31, pm} % \SmartUnit{hours=8, minutes=31, pm}
+ \SmartUnit{hours=9, minutes=3, am} % \SmartUnit{hours=9, minutes=3, am}
+ \SmartUnit{hours=0, minutes=0,seconds=1} % \SmartUnit{hours=0, minutes=0,seconds=1}
+ \SmartUnit{hours=12, minutes=0,seconds=1} % \SmartUnit{hours=12, minutes=0,seconds=1}
+ \end{lstlisting}
+
+ \item[Volume -- L, l, gal, gallons]
+ Converting between litres and gallons. Liters can be specified
+ using \textbf{L} or \textbf{l} and gallons can be given with
+ \textbf{gallons} or \textbf{gal}. Both UK gallons and USA
+ gallons are supported, with USA gallons being the default.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{l=10.0, places=1} % \SmartUnit{l=10.0, places=1}
+ \SmartUnit{L=10.0, places=1,uk} % \SmartUnit{L=10.0, places=1,uk}
+ \SmartUnit{gal=10.0, places=2} % \SmartUnit{gal=10.0, places=2}
+ \end{lstlisting}
+
+ \item[Weight -- kg, pounds, lbs]
+ \begin{lstlisting}[texcl]
+ \SmartUnit{kg=10.0, places=1} % \SmartUnit{kg=10.0, places=1}
+ \SmartUnit{pound=10.0, places=1} % \SmartUnit{pound=10.0, places=1}
+ \SmartUnit{pound=10.0,figures=1} % \SmartUnit{pound=10.0,figures=1}
+ \end{lstlisting}
+ \end{description}
+
+ \Section{Formatting options}
+
+ The following options can either be used inside \Verb|\SmartUnit| to
+ control the formatting \textit{locally} for just the unit being
+ printed. They can also be used as arguments to
+ \Verb|\SmartUnitSettings| to change the formatting of all subsequent
+ smart units (unless these settings are overridden locally). More
+ control over the formatting of the units is given by the
+ \Verb|\sisetup| macro from the \ctan{siunitx} package.
+
+ \begin{description}
+ \item[figures] This is equivalent to \Verb|\sisetup{round-mode=figures, precision=#1}|.
+ Units are printed with \#1 significant figures.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{miles=60, metric, figures=0} % \SmartUnit{miles=60, metric, figures=0}
+ \SmartUnit{miles=60, metric, figures=1} % \SmartUnit{miles=60, metric, figures=1}
+ \SmartUnit{miles=60, metric, figures=2} % \SmartUnit{miles=60, metric, figures=2}
+ \SmartUnit{miles=60, metric, figures=3} % \SmartUnit{miles=60, metric, figures=3}
+ \SmartUnit{miles=60, metric, figures=4} % \SmartUnit{miles=60, metric, figures=4}
+ \end{lstlisting}
+
+ \item[places]
+ This is equivalent to \Verb|\sisetup{round-mode=places, precision=#1}|.
+ Units are printed with \#1 decimal places.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{miles=60, metric, places=0} % \SmartUnit{miles=60, metric, places=0}
+ \SmartUnit{miles=60, metric, places=1} % \SmartUnit{miles=60, metric, places=1}
+ \SmartUnit{miles=60, metric, places=2} % \SmartUnit{miles=60, metric, places=2}
+ \SmartUnit{miles=60, metric, places=3} % \SmartUnit{miles=60, metric, places=3}
+ \SmartUnit{miles=60, metric, places=4} % \SmartUnit{miles=60, metric, places=4}
+ \end{lstlisting}
+
+
+ \item[imperial]
+ Print only Imperial units.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=1.0, imperial} % \SmartUnit{km=1.0, imperial, figures=2}
+ \SmartUnit{miles=1.0, imperial} % \SmartUnit{miles=1.0, imperial, figures=2}
+ \end{lstlisting}
+ \item[imperial metric]
+ Print Imperial units with metric units enclosed in brackets.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=1.0, imperial metric} % \SmartUnit{km=1.0, imperial metric, figures=2}
+ \SmartUnit{miles=1.0, imperial metric} % \SmartUnit{miles=1.0, imperial metric, figures=2}
+ \end{lstlisting}
+ \item[metric (default)]
+ Print only metric units.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=1.0, metric} % \SmartUnit{km=1.0, metric, figures=2}
+ \SmartUnit{miles=1.0, metric} % \SmartUnit{miles=1.0, metric, figures=2}
+ \end{lstlisting}
+ \item[metric imperial]
+ Print metric units with Imperial units enclosed in brackets.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=1.0, metric imperial} % \SmartUnit{km=1.0, metric imperial, figures=2}
+ \SmartUnit{miles=1.0, metric imperial} % \SmartUnit{miles=1.0, metric imperial, figures=2}
+ \end{lstlisting}
+ \item[uk]
+ Selects the UK variants of the Imperial units (currently this
+ only affects gallons):
+ \begin{lstlisting}[texcl]
+ \SmartUnit{l=1.0, imperial metric, figures=2,uk} % \SmartUnit{l=1.0, imperial metric, figures=2,uk}
+ \SmartUnit{gal=1.0, imperial metric, figures=2,uk} % \SmartUnit{gal=1.0, imperial metric, figures=2,uk}
+ \end{lstlisting}
+ \item[usa (default)]
+ Selects the USA variants of the Imperial units (currently this
+ only affects gallons):
+ \begin{lstlisting}[texcl]
+ \SmartUnit{l=1.0, imperial metric, figures=2,usa} % \SmartUnit{l=1.0, imperial metric, figures=2,usa}
+ \SmartUnit{gal=1.0, imperial metric, figures=2,usa} % \SmartUnit{gal=1.0, imperial metric, figures=2,usa}
+ \end{lstlisting}
+ By default \Verb|\SmartUnit| uses the American Imperial units.
+ This is a purely democratic choice dictated by the populations
+ of the two countries.
+ \end{description}
+
+ \Section{The code}
+ Behind the scenes, the \Verb|\SmartUnit| macro uses \ctan{pgfkeys} and
+ \ctan{pgfmath} to convert between the different units. The interface is
+ surprisingly simple and easy to extend. For example, the following
+ code takes care of the conversion between kilometers and miles:
+ \bgroup\footnotesize
+ \begin{lstlisting}
+ %%%% convert=distance: km <-> miles %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ km/.style={convert=distance, unit km=#1},%
+ mi/.style={convert=distance, unit miles=#1},%
+ miles/.style={convert=distance, unit miles=#1},%
+ distance/metric/.style={/SmartUnit/conversion={km}{miles}{0}{1.609344}{0}{km}},%
+ distance/imperial/.style={/SmartUnit/conversion={miles}{km}{0}{0.62137119}{0}{\text{mi}}},%
+ \end{lstlisting}
+ \egroup
+ \noindent
+ Most of the conversions are done in this way --- the exceptions are
+ ``length'' and ``time'', which are more complicated. The key
+ \Verb|/SmartUnit/conversion| is a macro that takes six arguments and
+ then implements the generic conversion formula:
+ \[
+ \text{New unit}(\Verb|#1|) = \Big(\text{Old unit}(\Verb|#2)|+\text{Pre-offset}(\Verb|#3|)\Big)*\text{Multiplier}(\Verb|#4|) + \text{Post-offset}(\Verb|#5|),
+ \]
+ where \Verb|#6| is the metric or Imperial symbol for the unit being
+ printed.
+
+ \textit{Adding additional conversions is quite straightforward and I am
+ happy to incorporate suggestions.}
+
+ There is, of course, some trickery driving how the units are printed.
+ Here is the definition of \Verb|\SmartUnit|:
+ \begin{lstlisting}
+ \newcommand\SmartUnit[1]{%
+ \bgroup%=> changes are local to \SmartUnit => no need to reset
+ \pgfkeys{/SmartUnit,#1}% Pass the keys to /SmartUnit
+ \pgfkeys{/SmartUnit,printunit}% Calculate units and print
+ \egroup%
+ }
+ \end{lstlisting}
+ So \Verb|\SmartUnit| calls \ctan{pgfkeys} twice: the first time to
+ set the keys and the second time to print them using
+ \Verb|/SmartUnit/printunit|. In turn, this uses
+ \Verb|/SmartUnit/convert| to identify the unit being printed,
+ after which the pgf key
+ \Verb|/SmartUnit/output| is called. This has subkeys for the four
+ different \textit{output formats}:
+ \begin{center}
+ \texttt{metric}, \texttt{imperial},
+ \texttt{metric imperial} and \texttt{imperial metric}.
+ \end{center}
+ Finally, \Verb|/SmartUnit/output/<format>| uses
+ \Verb|/SmartUnit/convert| to perform the required conversion.
+ This multi-step printing process is necessary for converting between
+ inputs like time or centimeters, feet and inches, where the
+ output units depend on more than one input value. It is also used to
+ print the four different output formats discussed above.
+
+
+ \Section{Acknowledgement}
+ The package was written in response to a
+ \href{http://tex.stackexchange.com/questions/241169/}{TeX.SX question},
+ partly as a proof-of-concept and partly as an exercise to learn how
+ to use \ctan{pgfkeys}. Thanks to Mark Adams for asking the question.
+
+ \Section{Author}
+ \href{mailto:Andrew.Mathas@gmail.com?smartunits}{Andrew Mathas},
+ \copyright\space 2015, 2016.
+
+ \Section{Licence}
+ Released under the
+ \href{http://www.latex-project.org/lppl.txt}%
+ {LaTeX Project Public License}, v1.3c or later.
+
+\end{document}