pgfmath 中的嵌套条件

pgfmath 中的嵌套条件

\dx==0当为真时,以下代码将引发除以 0 的错误:

\pgfmathsetmacro{\rot}{(
  \dx==0 ? (\dy > 0 ? 90 : -90) : (\dx>0 ? atan(\dy/\dx) : 180+atan(\dy/\dx))
)}

\rot即使条件为真,代码设置\dx==0也正确,但似乎解析器仍在继续分析错误子句,即使条件为真。有人知道我做错了什么吗?完整代码如下:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepgfmodule{oo}
%http://tex.stackexchange.com/questions/33703/extract-x-y-coordinate-of-an-arbitrary-point-in-tikz
\makeatletter
\newcommand{\gettikzxy}[3]{%
  \tikz@scan@one@point\pgfutil@firstofone#1\relax
  \edef#2{\the\pgf@x}%
  \edef#3{\the\pgf@y}%
}
\makeatother

\pgfooclass{rr}{
  \method rr(#1,#2) { % The constructor; everything is done in here
    % Here I can get named x and y coordinates
    \gettikzxy{(#1)}{\spx}{\spy}
    \gettikzxy{(#2)}{\epx}{\epy}
    % I'd like named points to work with
    \coordinate (Start) at (\spx, \spy) node[right]{start};
    \coordinate (End) at (\epx, \epy);
    % Find the length between start and end. Then the angle between x axis and Diff will be the rotation to apply.
    \coordinate (Diff) at ($ (End)-(Start) $);
    \gettikzxy{(Diff)}{\dx}{\dy}
    \pgfmathparse{veclen(\dx, \dy)} \pgfmathresult
    \let\length\pgfmathresult
    \node[right] at (End) {\length};
    \pgfmathsetmacro{\rot}{(
      \dx==0 ? (\dy > 0 ? 90 : -90): (\dx>0 ? atan(\dy/\dx) : 180+atan(\dy/\dx))
    )}
    \begin{scope}   [rotate around = {\rot:(\spx, \spy )}]
      \draw ($ (Start)+(0,\hi) $) arc(90:270:\hi) -- +(\length pt, 0) arc(-90:90:\hi) -- cycle;
    \end{scope}
  }
}

\begin{document}
\begin{tikzpicture}
  \coordinate (A) at (0,0);
  \coordinate (B) at (0,16);
  \def\hi{0.25}
  \pgfoonew \AB=new rr(A,B);
  \fill (A) circle (3pt);
  \fill (B) circle (3pt);
\end{tikzpicture}
\end{document}

答案1

是的,简写符号的所有组成部分都会被求值,即使只有一个分支会跟随。以下简单公式会产生相同的错误:

\pgfmathparse{1==2 ? 3/0 : 4}\pgfmathresult

由于 1 不是 2,结果应该是 4,但编译器仍然评估 3/0。

解决这个问题的一个简单方法是使用 TeX 条件,除非必要,否则不会进行评估。因此,我们首先评估是否\dx==0使用\pgfmathparse,然后对 进行条件(使用 TeX 基元)\pgfmathresult

那是,

\pgfmathsetmacro{\rot}{(
  \dx == 0 ? (\dy > 0 ? 90 : -90) : (\dx > 0 ? atan(\dy / \dx) : 180 + atan(\dy / \dx))
)}

变成

\pgfmathparse{\dx == 0}%
\ifnum\pgfmathresult=1 % \dx == 0
  \pgfmathsetmacro{\rot}{\dy > 0 ? 90 : -90}
\else% \dx != 0
  \pgfmathsetmacro{\rot}{\dx > 0 ? atan(\dy / \dx) : 180 + atan(\dy / \dx)}
\fi

相关内容