我的问题如下
这个关于使用\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}