6

My question follows this one about formatting coordinate using \ang{} command of the siunitx package.

When listing coordinate on a map, it is required to use two digits for minutes and seconds. As for degrees it depends whether it is a latitude or a longitude.

For the latitude, the angle is between 0 and 90, so degrees need two digits, hence the \ang[minimum-integer-digits=2]{2;3;4} will be formatted correctly.

My question concern the longitude, since it is between 0 and 180 degrees, it need 3 digits. One can try \ang[minimum-integer-digits=3]{2;3;4} but the result is 002°003'004", which is not what is needed. A way to avoid this is to use \ang[parse-numbers=false]{002;03;04}, but we now need to manualy enter the missing 0.

Is there a way to automaticaly add these zero for the longitude?

2

Here's a way to do it with a wrapper command called \longitude. Could likely be optimized, but this evaluates each digit and adds zeros as necessary (with a few examples):

 \documentclass[10pt]{article}

 \usepackage{siunitx}

 \newcommand\longitude[1]{%
    %Commands to extract the components
    \def\extrang##1;##2;##3;{##1}
    \def\extrmin##1;##2;##3;{##2}
    \def\extrsec##1;##2;##3;{##3}
    %Extract components
    \edef\angval{\extrang #1;}
    \edef\minval{\extrmin #1;}
    \edef\secval{\extrsec #1;}
    %Evaluate magnitude, define result
    \ifnum\angval<100
        \ifnum\angval<10
            \edef\newangval{00\angval}
        \else
            \edef\newangval{0\angval}
        \fi
    \else
        \edef\newangval{\angval}
    \fi
    \ifnum\minval<10
        \edef\newminval{0\minval}
    \else
        \edef\newminval{\minval}
    \fi
    \ifnum\secval<10
        \edef\newsecval{0\secval}
    \else
        \edef\newsecval{\secval}
    \fi
    %Pass formatted result to \ang
    \edef\rslt{\noexpand\ang[parse-numbers=false]{\newangval;\newminval;\newsecval}}
    \rslt
 }
 \begin{document}
 \longitude{90;2;45}\par
 \longitude{100;20;4}\par
 \longitude{1;28;6}\par
 \end{document}  

enter image description here

Edit: To use the above approach with babel, the ; shorthand needs to be disabled with either shorthands=off in the options or \shorthandoff{;} in the body. If you want to keep the ; shorthand available, the passed string can be detokenized prior to processing:

 \documentclass[10pt]{article}

 \usepackage{siunitx}
 \usepackage[frenchb]{babel}

 \newcommand\longitude[1]{%
    %Commands to extract the components
    \def\extrang##1;##2;##3){##1}
    \def\extrmin##1;##2;##3){##2}
    \def\extrsec##1;##2;##3){##3}
    %Extract components
    \edef\angval{\expandafter\extrang\detokenize{#1})}
    \edef\minval{\expandafter\extrmin\detokenize{#1})}
    \edef\secval{\expandafter\extrsec\detokenize{#1})}
    %Evaluate magnitude, define result
    \ifnum\angval<100
        \ifnum\angval<10
            \edef\newangval{00\angval}
        \else
            \edef\newangval{0\angval}
        \fi
    \else
        \edef\newangval{\angval}
    \fi
    \ifnum\minval<10
        \edef\newminval{0\minval}
    \else
        \edef\newminval{\minval}
    \fi
    \ifnum\secval<10
        \edef\newsecval{0\secval}
    \else
        \edef\newsecval{\secval}
    \fi
    %Pass formatted result to \ang
    \edef\rslt{\noexpand\ang[parse-numbers=false]{\newangval;\newminval;\newsecval}}
    \rslt
 }
 \begin{document}
 \longitude{90;2;45}\par
 \longitude{100;20;4}\par
 \longitude{1;28;6}\par
 \end{document} 

Which yields the same as above with or without the babel package.

  • I believe that only the minutes and seconds need to be "padded" with zeros; the degrees portions are OK to be printed as single-digit or two-digit numbers. – Mico Nov 5 '15 at 4:27
  • @Mico: The OP has \ang[parse-numbers=false]{002;03;04} as a possible work around but wanted an approach that didn't require the manual addition of the 0s. I may have misunderstood the question. – Guho Nov 5 '15 at 4:39
  • I wrote "I believe that..." deliberately -- I may have misunderstood the question as well! Let's see if the OP weighs in with more information. – Mico Nov 5 '15 at 4:43
  • @Guho Thank's for this command. And you are right, the degree part need 3 digits. There is a clash with option frenchb of the babel package. The error message indicate a extra }, is there a way to overcome this? – Alain Remillard Nov 5 '15 at 18:09
  • @AlainRemillard: The easiest way is to add \shorthandoff{;} after \begin{document} or disable all of the shorthands with \usepackage[shorthands=off,frenchb]{babel}. – Guho Nov 5 '15 at 21:22
3

If you can use LuaLaTeX instead of pdfLaTeX, it's possible to set up a Lua function and a TeX "wrapper macro" to perform the task of formatted printing of longitude. (Speaking for myself, I find that writing a Lua function is a more straightforward exercise than hacking/augmenting the \ang macro would be...)

The TeX-side "wrapper macro", named \longitude in the example below, takes one input. It is assumed that one or more non-numeric characters -- ,, ;, even "" (space) is permitted -- separate the degrees, minutes, and seconds portions of the input.

Note that no input validity checking is performed, i.e., the macro doesn't check whether or not the degree portion exceeds 180 or the minute and second portions exceed 59.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}

%% Lua-side code
\usepackage{luacode}
\begin{luacode}
function longitude ( s )
  deg, min, sec = string.match( s, "([%+%-]?%d+)%D+(%d+)%D+(%d+)" )
  return tex.sprint( string.format ( 
       "$".."%03d".."^{\\circ}".."%02d".."'".."%02d".."''$" , 
       tonumber(deg), tonumber(min), tonumber(sec) ))
end
\end{luacode}

%% TeX-side code
\newcommand\longitude[1]{\directlua{ longitude ( \luastring{#1} ) }}

\begin{document}
\longitude{179,59,59}

\longitude{0;0;0}

\longitude{1 2  3}
\end{document} 
  • Great answer, sadly I don't use lualatex, so I wont be able to use it. But you gave me a reason to learn it. On the other hand, the degree part need to have 3 digits, as pointed out in a comment to the answer of @Guho. – Alain Remillard Nov 5 '15 at 17:47
  • @AlainRemillard - Thanks for clarifying that the degrees portion needs to show three digits, padding with zeros if needed; I'll amend my code accordingly. About LuaLaTeX vs pdfLaTeX: it's really not difficult or tricky to use LuaLaTeX. You can search this site for postings (and answers) regarding the difference between the two formats and what, if anything, needs to be changed in a document so that it can be compiled under LuaLaTeX instead of pdfLaTeX. – Mico Nov 5 '15 at 21:19
  • 1
    Thank's for the updated solution. I now have a reason to learn lualatex. – Alain Remillard Nov 6 '15 at 16:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.