含钛钾Z 使用calc
库你可以写类似的东西
\node (A) at ($(0,0)!0.75!(1,1)$) {};
或者你可以写一些(相当不同的东西)
\node (B) at ($(0,0)!2in!(1,1)$) {};
我想要做的是创建一个接受标量或维度参数的命令。
我天真地想做类似的事情
\def\test#1{\ifdim#1\relax ... \else ... \fi}
当然,这是完全错误的,因为\ifdim
比较的是两个维度的值。所以我真正想要的是
\def\test#1{\ifIsDimension#1\relax ... \else ... \fi}
有什么建议我该如何做吗?
答案1
如果你不介意pgfmath
解析器的开销,你可以解析数字并检查\ifpgfmathunitsdeclared
。如果指定了 TeX 单位,则情况确实如此在任何时候在表达式中,或者如果表达式包含 TeX 认为具有单位的内容,例如跳过和盒子尺寸。
\documentclass[border=0.125cm]{standalone}
\usepackage{pgfmath,pgffor}
\parindent0pt
\def\print#1{\expandafter\Print#1@}
\def\Print#1{\if#1@\else\string#1\relax\expandafter\Print\fi}
\begin{document}
\newcount\mycount
\newdimen\mydimen
\newskip\myskip
\mycount=1
\mydimen=1pt
\myskip=1pt plus 1pt
\newbox\mybox
\setbox\mybox=\hbox{1}
\begin{minipage}{3in}
\foreach \value in {1, 1.0, 1e0, sin(1), 1cm, 1pt, 1mm, 1sp, 1mu, sin(1pt), 1+1pt,
\mycount, \mydimen, \myskip, \wd\mybox, \mycount+1pt, width("1")}{%
\pgfmathparse{\value}
Expression \hbox to 2.5cm{\hfill`{\tt\print\value}'}
\ifpgfmathunitsdeclared
\emph{\bfseries has} a unit
\else
has no units
\fi
}
\end{minipage}
\end{document}
还值得注意的是,\pgfmathpostparse
在解析器完成之后但在退出之前会执行一个宏,其中可以完成进一步的操作。最初将其设置为,\relax
但建议检查其值,以防某些库或其他包更改它。
解析的结果将会\pgfmathresult
是可能的来改变它(如果有人真的想的话)。然而它仍然在 TeX 组内,因此\global
如果需要某些测试的结果,就必须使用它。
下面使用粗略整数测试的例子并不好,因为解析器很少返回整数(下面显示了一些例外)但说明了如何使用它。
\documentclass[border=0.125cm]{standalone}
\usepackage{pgfmath,pgffor}
\parindent0pt
\makeatletter
\newif\ifpgfmathresultinteger
\def\pgfmathpostparse{%
\expandafter\pgfutil@in@\expandafter.\expandafter{\pgfmathresult}%
\ifpgfutil@in@%
\global\pgfmathresultintegerfalse%
\else%
\global\pgfmathresultintegertrue%
\fi%
}
\def\print#1{\expandafter\Print#1@}
\def\Print#1{\if#1@\else\string#1\relax\expandafter\Print\fi}
\begin{document}
\newcount\mycount
\newdimen\mydimen
\mycount=1
\mydimen=1pt
\begin{minipage}{3.5in}
\foreach \value in {1, int(1.0), \mycount, \mydimen, int(\mydimen+1pt), \mycount+1pt}{%
\pgfmathparse{\value}
Parsing \hbox to 3.5cm{\hfill`{\tt\print\value}'}
does
\ifpgfmathresultinteger
\else
\emph{\bfseries not}
\fi
give an integer
}
\end{minipage}
\end{document}
答案2
这当然很慢,但应该处理所有情况(数字、尺寸、错误输入)。
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand{\IfIsDim}{mmm}
{
\aellet_ifisdim:nnn { #1 } { #2 } { #3 }
}
\tl_new:N \l_aellet_ifisdim_arg_tl
\bool_new:N \l_aellet_ifisdim_has_unit_bool
\regex_const:Nn \c_aellet_unit_regex { (pt|pc|in|bp|cm|mm|dd|cc|sp|em|ex|px)\s*\Z }
\regex_const:Nn \c_aellet_number_regex { \A\s*(\+|\-)*[0-9]*\.?[0-9]*\s*\Z }
\cs_new_protected:Npn \aellet_ifisdim:nnn #1 #2 #3
{
\tl_set:Nn \l_aellet_ifisdim_arg_tl { #1 }
\regex_match:NnTF \c_aellet_unit_regex { #1 }
{% there is a unit of measure at the end
\bool_set_true:N \l_aellet_ifisdim_has_unit_bool
\regex_replace_once:NnN \c_aellet_unit_regex { } \l_aellet_ifisdim_arg_tl
}
{% no unit of measure
\bool_set_false:N \l_aellet_ifisdim_has_unit_bool
}
\regex_match:NVTF \c_aellet_number_regex \l_aellet_ifisdim_arg_tl
{
\bool_if:NTF \l_aellet_ifisdim_has_unit_bool { #2 } { #3 }
}
{
\ERROR
}
}
\cs_generate_variant:Nn \regex_match:NnTF { NV }
\ExplSyntaxOff
\IfIsDim{3.5pt}{\typeout{IS DIM}}{\typeout{IS NUMBER}}
\IfIsDim{3.5}{\typeout{IS DIM}}{\typeout{IS NUMBER}}
\IfIsDim{-3}{\typeout{IS DIM}}{\typeout{IS NUMBER}}
\IfIsDim{+--.5}{\typeout{IS DIM}}{\typeout{IS NUMBER}}
\IfIsDim{ .5 }{\typeout{IS DIM}}{\typeout{IS NUMBER}}
\IfIsDim{3.5 in}{\typeout{IS DIM}}{\typeout{IS NUMBER}}
\IfIsDim{3.5pq}{\typeout{IS DIM}}{\typeout{IS NUMBER}}
\stop
这是终端上的输出
IS DIM
IS NUMBER
IS NUMBER
IS NUMBER
IS NUMBER
IS DIM
! Undefined control sequence.
<argument> \ERROR
l.41 ...pq}{\typeout{IS DIM}}{\typeout{IS NUMBER}}
?
答案3
以下是 PSTricks 设置带或不带单位的长度的方式(使用 运行tex
):
\catcode`\@=11
\newdimen\psunit \psunit=10pt% the current unit, can be any value
\def\pstunit@off{\let\@psunit\ignorespaces\ignorespaces}
%
\def\pssetlength#1#2{% #1: dimen #2 value (unit)
\let\@psunit\psunit
\afterassignment\pstunit@off
#1 #2\@psunit}
\pssetlength\psunit{2} \the\psunit % 2 times of the current unit
\pssetlength\psunit{1cm} \the\psunit % absolute 1cm, the new current unit and so on
\bye
这真的很简单:
- 如果
#2
没有单位,则尺寸#1
设置为#2\@psunit
,并且\afterassignment
没有意义,因为它被执行后 长度设置。 - 如果
#2
有单位,则尺寸#1
设置为#2
,以下\@psunit
就像\ignorespaces
;它被重新定义\afterassignment
。
答案4
我使用了 A. Ellet 的答案,但将其缩短为
\def\isdimen#1{\afterassignment\isdimen@\tempdimen=#1em\relax}
\def\isdimen@#1\relax{\ifx&\expandafter\@secondoftwo\else \expandafter\@firstoftwo\fi}
另外,你可以使用相同的想法来检查某个东西是否是整数:
\def\isint#1{\afterassignment\isint@\tempcount=#1\relax}
\def\isint@#1\relax{\ifx&\expandafter\@firstoftwo\else \expandafter\@secondoftwo\fi}
遗憾的是,这些是不可扩展的。
此外,如果您想使用路由\pgfmathparse
来检查某个东西是否为整数,则以下可扩展宏可以检查的值是否\pgfmathresult
为n
或 的形式n.0
。
\def\ifpgfmathresultisint{\expandafter\ifpgfmathresultisint@\pgfmathresult..\nil}
\def\ifpgfmathresultisint@#1.#2.#3\nil{%
\ifx\nil#2\nil
\expandafter\@firstoftwo
\else
\ifnum#2=0
\expandafter\expandafter\expandafter\@firstoftwo
\else
\expandafter\expandafter\expandafter\@secondoftwo
\fi
\fi
}