2

The following code throws a division by 0 error when \dx==0 is true:

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

The code sets \rot correctly, even when \dx==0 is true but it seems that the parser is continuing to analyze the false clause even though the condition was true. Anyone know what I'm doing wrong? Full code below:

\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 Answer 1

2

Yes, all components of the shorthand notation are evaluated, even though only one of the branches will be following. The following simple formula provides the same error:

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

Since 1 is not 2, the result should be 4, but the compiler still evaluates 3/0.

One easy way around this is to use TeX conditionals which doesn't evaluate unless necessary. So, we first evaluate whether \dx==0 using \pgfmathparse and then condition (using TeX primitives) on \pgfmathresult.

That is,

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

becomes

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .