2

I have made a command \tl{x} to "turn left x degrees". Because this is arc and coordinate juggling I have written some test code. Attached is the MWE:

\documentclass[x11names]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{calculator}

\makeatletter
\def\extractcoord#1#2#3{
  \path let \p1=(#3) in \pgfextra{
    \pgfmathsetmacro#1{\x{1}/\pgf@xx}
    \pgfmathsetmacro#2{\y{1}/\pgf@yy}
    \xdef#1{#1} \xdef#2{#2}
  };
}

\newcommand{\tl}[1]{
  \draw[fill] (\oXPos, \oYPos) coordinate (P) circle (0.5mm) node[right] {P};  
  \ADD{\oDir}{#1}{\oDirNew}
  \draw (\oXPos,\oYPos) arc (\oDir:\oDirNew:\oRad) coordinate (Z);
  \draw (Z) circle (1mm) node[left] {Z};
  \COPY{\oDirNew}{\oDir}
  \extractcoord\oXPos\oYPos{Z}
}

\begin{document}

\def\oRad{20}
\def\oDir{0}
\def\oXPos{0}
\def\oYPos{0}

\begin{tikzpicture}[x=1mm, y=1mm]
\foreach \x in {1,2} {
  \tl{90}
} 
\end{tikzpicture}

\def\oRad{20}
\def\oDir{0}
\def\oXPos{0}
\def\oYPos{0}

\begin{tikzpicture}[x=1mm, y=1mm]
  \tl{90}
  \tl{90}
\end{tikzpicture}
\end{document}
}

You see the tl-command and the test code: foreach-call and manual-double-call.

Surprisingly the foreach is different from the double manual call. Maybe it has something to do with the way I handle the variables and maybe with the calculator package.

The foreach produces the upper graphic, the manual call below. The lower graphic would be the expected behavior.

enter image description here

Can you explain this? Obviously there is something wrong with my tl-code.

2
  • I think you want \xdef\oDir{\oDirNew} instead of \COPY{\oDirNew}{\oDir} to make the new direction global, i.e. known in the next step. However, I would like to draw your attention to /tikz/turn which is described on p. 144 of pgfmanual v3.1.4.
    – user194703
    Oct 27 '19 at 23:46
  • boy, I Should read the manual more often. Thanks, I'm ashamed :-)
    – texpiet
    Oct 28 '19 at 16:38
4

What is going on here? \foreach loops start a group. Your change of \oDir is only local. So in the next step still the old value of \oDir is used. What can you do about it?

  1. A blunt way of rectifying this is to make the redefinition global by using \xdef\oDir{\oDirNew} instead of \COPY{\oDirNew}{\oDir}. However, the price you pay is that \oDir is global.
  2. Another way, which does not make the \oDir global, is to use the remember key of \foreach loops.

I am illustrating the second way since it is less known.

\documentclass[x11names]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{calculator}

\makeatletter
\def\extractcoord#1#2#3{
  \path let \p1=(#3) in \pgfextra{
    \pgfmathsetmacro#1{\x{1}/\pgf@xx}
    \pgfmathsetmacro#2{\y{1}/\pgf@yy}
    \xdef#1{#1} \xdef#2{#2}
  };
}

\newcommand{\tl}[1]{
  \draw[fill] (\oXPos, \oYPos) coordinate (P) circle (0.5mm) node[right] {P};  
  \ADD{\oDir}{#1}{\oDirNew}
  \draw (\oXPos,\oYPos) arc (\oDir:\oDirNew:\oRad) coordinate (Z);
  \draw (Z) circle (1mm) node[left] {Z};
  \COPY{\oDirNew}{\oDir}
  \extractcoord\oXPos\oYPos{Z}
}

\begin{document}

\def\oRad{20}
\def\oDir{0}
\def\oXPos{0}
\def\oYPos{0}

\begin{tikzpicture}[x=1mm, y=1mm]
\foreach \x [remember=\oDir as \oDir] in {1,2} {
  \tl{90}
} 
\end{tikzpicture}

\def\oRad{20}
\def\oDir{0}
\def\oXPos{0}
\def\oYPos{0}

\begin{tikzpicture}[x=1mm, y=1mm]
  \tl{90}
  \tl{90}
\end{tikzpicture}
\end{document}

enter image description here

Let me also mention that TikZ has the turn key, which you could use here. It is described on p. 144 of the pgfmanual v3.1.4.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.