10

I am trying to put some TikZ pictures into a Beamer slide to enhance readability. The position of the TikZ pictures on the slide will depend on how much text comes before. Since there will be many TikZ pictures, and each will have to be adjusted by the same amount if I change the text at the top of the slide, I tried to make a macro to avoid having to adjust the position of each TikZ picture manually each time I change the text..

Consider the following code:

\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\pgfmathsetmacro{\yoff}{5}    
\newcommand{\print}[1]{\pgfmathparse{#1}\pgfmathresult}
\begin{frame}
  \frametitle{Testing}
  \begin{itemize}
  \item Test picture
  \begin{picture}(0, 0)
     \put(0,\print{8+\yoff}){
         \tikz \draw[red,thick] (0,0) ellipse (5pt and 5pt);
      }
  \end{picture}
  \end{itemize}
\end{frame}
\end{document}

Here I get the following error:

! Missing number, treated as zero.

  \begingroup 

l.17 \end{frame}

However, putting the macro within the \frametitle of the slide works as expected (without errors):

\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\pgfmathsetmacro{\yoff}{5}
\newcommand{\print}[1]{\pgfmathparse{#1}\pgfmathresult}
\begin{frame}
  \frametitle{Testing \print{8+\yoff}}
  \begin{itemize}
  \item Test picture
    \begin{picture}(0, 0)
      \put(0,\yoff){
          \tikz \draw[red,thick] (0,0) ellipse (5pt and 5pt);
       }
     \end{picture}
  \end{itemize}
\end{frame}
\end{document}

1 Answers1

8

\put needs something that expands to a number:

\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\def\yoff{5}    
\newcommand{\print}[1]{\pgfmathparse{#1}\pgfmathresult}
\begin{frame}
  \frametitle{Testing}
  \begin{itemize}
  \item Test picture
  \begin{picture}(0, 0)
     \put(0,\numexpr8+\yoff\relax){
         \tikz \draw[red,thick] (0,0) ellipse (5pt and 5pt);
      }
  \end{picture}
  \end{itemize}
\end{frame}

\end{document}

If you want to use decimal arithmetic with non integral values you need to add pt use dimen arithmetic and then remove the pt

 \put(0,\csname strip@pt\endcsname\dimexpr8pt+\yoff pt\relax){

would work for example.

David Carlisle
  • 757,742
  • Thank you! If I replace \def\yoff{5} with \pgfmathsetmacro{\yoff}{5} I get the error message: ! Illegal unit of measure (pt inserted) – Håkon Hægland Jan 15 '13 at 10:25
  • 1
    yes that's why I changed it:-) \pgfmathsetmacro{\yoff}{5} sets yoff to 5.0 not 5 and that isn't a number according to primitive TeX number syntax (which has to be an integer literal) – David Carlisle Jan 15 '13 at 10:30
  • Ok, I see:) But \put accepts decimal numbers like \put(1.3,2.5).. What if I define \def\yoff{5.5}.. How can I deal with this situation? – Håkon Hægland Jan 15 '13 at 10:48
  • 1
    updated answer for that case – David Carlisle Jan 15 '13 at 10:56
  • @DavidCarlisle You could always use the L3 FPU :-) – Joseph Wright Jan 15 '13 at 11:22
  • With the picture package (by Heiko Oberdiek) one can also use \put(<dimen>,<dimen>) – egreg Jan 15 '13 at 12:49
  • @DavidCarlisle :There is still one thing I do not understand.. In your first answer you said that \put needs something that expands to a number, and later you say that 5.0 is not a number according to primitive TeX, next we use the strip@pt to create something like, e.g., 9.5.. Now suddenly \put accepts a decimal.. What am I missing here? – Håkon Hægland Jan 15 '13 at 14:51
  • I sort of lied:-) It needs to work by expansion to something that can be used as a multiplier for \unitlength so 5.0 is OK. So an addition method that uses (say) \def to store intermediate results would not work. So "number" there was rather loose and included decimal values. But in \numexpr It has to be what TeXBook calls <number> which is essentially an integer as used by latex counters etc. So there I switched meaning of number to that technical syntax production, sorry. – David Carlisle Jan 15 '13 at 15:14
  • I am not sure I understand.. I also find the following puzzling: I cannot use \put(0,\print{8+\yoff}), however I can define another variable say \ytest using the following code on the line before \put : \pgfmathparse{8+\yoff} \pgfmathsetmacro{\ytest}{\pgfmathresult} , and then use \put(0,\ytest) which now works.. Maybe this is somehow related to the following post : store-pgfmathresult-in-a-variable ? – Håkon Hægland Jan 15 '13 at 16:30
  • 2
    yes that \print command does not just work via expansion it defines internal macros as part of its definition so it can not be used inline in \put. It is exactly the same as you can go \def\foo{3pt} \dimen@=\foo but you can not go \dimen@=\def\foo{3pt}\foo you can not have the definition inline in teh length setting, it has yo be first, or not there at al \dimen@=3pt – David Carlisle Jan 15 '13 at 18:15
  • Thank you! This sounds reasonable.. But then, why can I use \print inline in \frametitle (but not in \put) ? – Håkon Hægland Jan 15 '13 at 18:40
  • well the frametitle is just typestting stuff which is what \print is presumably intended for so it doesn't matter how many definitions it makes internally, but the arguments to \put are passed to a length assignment so have to expand to a something that is legal in \dimen@=...\unitlength – David Carlisle Jan 15 '13 at 19:54
  • Ok sorry for all the questions.. I think it all reduces to that I do not know the macro expansion rules in LaTeX :) Anyway I have learned a lot from this discussion.. – Håkon Hægland Jan 15 '13 at 21:01