使用 siunitx 格式化经度

使用 siunitx 格式化经度

我的问题如下 这个关于使用\ang{}siunitx 包的命令格式化坐标。

在地图上标示坐标时,分和秒必须用两位数,至于度数则要看是纬度还是经度。

对于纬度,角度介于 0 到 90 之间,所以度数需要两位数字,因此\ang[minimum-integer-digits=2]{2;3;4}格式正确。

我的问题与经度有关,因为它介于 0 到 180 度之间,所以需要 3 位数字。你可以尝试,\ang[minimum-integer-digits=3]{2;3;4}但结果是 002°003'004",这不是所需的。避免这种情况的一种方法是使用\ang[parse-numbers=false]{002;03;04},但我们现在需要手动输入缺失的 0。

有没有办法自动在经度中添加这些零?

答案1

以下是使用名为 的包装器命令执行此操作的一种方法\longitude。可能会进行优化,但这会评估每个数字并根据需要添加零(附几个示例):

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

在此处输入图片描述

编辑:要使用上述方法babel,需要在选项或正文中;禁用简写。如果要保留简写,可以在处理之前对传递的字符串进行去标记化:shorthands=off\shorthandoff{;};

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

无论有没有babel包装,其结果都与上面相同。

答案2

如果您可以使用 LuaLaTeX 而不是 pdfLaTeX,则可以设置 Lua 函数和 TeX“包装器宏”来执行格式化打印经度的任务。(就我个人而言,我发现编写 Lua 函数比破解/增强宏更简单\ang……)

TeX 端的“包装宏”,名为\longitude如下例所示)接受一个输入。假设有一个或多个非数字字符—— ,、、;甚至“ ”(空格)都是允许的——将输入的度、分、秒部分分隔开。

请注意,没有执行输入有效性检查,即宏不会检查度数部分是否超过 180 或分秒部分是否超过 59。

在此处输入图片描述

% !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} 

相关内容