17

Why can't I use the outcome of using pgfmath in a TikZ coordinate?

Here is a (minimal) example that does not work:

\documentclass[11pt]{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}

\newcommand{\leftBoundary}{\pgfmathparse{0.255in*3/2}\pgfmathresult}

% This is fine:
\node at (0,0) {\leftBoundary};

% This does not work:
\draw[thick] (\leftBoundary,2) rectangle +(1,1);

\end{tikzpicture}
\end{document}

What I'm trying to achieve is to compute a number of dimensions that I then use for arranging things in a figure. While I know that I could also use code like ($(point1)+(3,4)$) during drawing stuff in TikZ, for better overview, it would be great if the dimensions can be computed upfront.

  • If you take the pgfmathparse out from the command definition, the rest would work just fine. – percusse May 5 '13 at 8:07
17

No, that doesn’t work because TikZ only accepts fully expandable input.

By the way, the coordinate input is thrown into PGF math anyway, so

\draw[thick] (0.255in*3/2,2) …

works just as well (case 1).

You can also just store 0.255in*3/2 in \leftBoundary and use that macro (case 2; again, using that anything will be parsed through the mathematical engine of PGF anyway).

Of course, for very exhausting calculation or for often-used values, you may pre-calculate some values beforehand and use the parsed and calculated result.

For this, you will need to use

\pgfmathsetmacro\leftBoundary{0.255in*3/2}

(case 3) or

\pgfmathparse{0.255in*3/2}\let\leftBoundary\pgfmathresult

(which is more or less the same thing as long as the result is a number).

Both will set \leftBoundary to the resulting value in pt but without a unit. TikZ will then interprets this value in the standard user coordinate system, which suddenly makes your TikZ picture nearly 28 cm wide. You will need to append pt again in the path.

Very helpful here is (besides using a real TeX dimension, case 5) the macro \pgfmathsetlengthmacro which appends pt to the resulting value on its own (case 4).


You might wonder why I used a + in the cases 3, 4 and 5. As said at the beginning, TikZ throws most of its input through PGF math anyway.

A preceeding + though will disable the math parsing “and a simple assignment or increment is done using normal TeX assignments or increments. This will be orders of magnitude faster than calling the parser.” (PGF manual, v 2.10, section 62.1 “Commands for Parsing Expressions”, p. 527)

For cases 3 and 4 this can be applied because \leftBoundary contains only 27.6438pt, in case 5 \leftBoundary is actually a dimension (length) and is made for TeX’s assignments.

Preceeding a + in cases 1 and 2 will result in typesetting *3/2 in the TikZ picture as 0.255in is a legal TeX assignment:

enter image description here

Using +3/2*0.255in (which would have been legal in PGF math) will result in an error from TeX.

How much this actually matter (in terms of compilation time), I never have tested it thoroughly.

 When in doubt,
  leave it out.

Code

\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{backgrounds}\tikzset{every picture/.append style={framed}}
\begin{document}
\begin{tikzpicture}
\node at (0,0) {$(0,0)$};
\draw[thick] (0.255in*3/2,2) rectangle +(1,1) node[midway] {1};
\end{tikzpicture}

\begin{tikzpicture}
\newcommand*{\leftBoundary}{0.255in*3/2}
\node at (0,0) {$(0,0)$};
\draw[thick] (\leftBoundary,2) rectangle +(1,1) node[midway] {2};
\end{tikzpicture}

\begin{tikzpicture}
\pgfmathsetmacro\leftBoundary{0.255in*3/2}
\node at (0,0) {$(0,0)$};
\draw[thick] (+\leftBoundary pt,2) rectangle +(1,1) node[midway] {3};
\end{tikzpicture}

\begin{tikzpicture}
\pgfmathsetlengthmacro\leftBoundary{0.255in*3/2}
\node at (0,0) {$(0,0)$};
\draw[thick] (+\leftBoundary,2) rectangle +(1,1) node[midway] {4};
\end{tikzpicture}

\begin{tikzpicture}
\newdimen\leftBoundary % or \newlength\leftBoundary
\pgfmathsetlength\leftBoundary{0.255in*3/2}
\node at (0,0) {$(0,0)$};
\draw[thick] (+\leftBoundary,2) rectangle +(1,1) node[midway] {5};
\end{tikzpicture}
\end{document}

Output (Example)

enter image description here

  • Indeed. Great explanation! So the input to tikz for coordinates has to be fully expandable. In any case, "\pgfmathsetlengthmacro" seems to be the way to go. Thank you! – DCTLib May 4 '13 at 20:16
  • What about allowing arguments to pgfsetmacro? – DiTTiD Mar 29 '18 at 9:03

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.