2

This question already has an answer here:

I have already seen \widthof within tikzpicture, but this is slightly different.

I have a rather complex Tikz image, which I'd like to eventually include in a Latex document; as such, I'd like this .tikz file to be as self contained as possible. There are a bunch of commands in there relevant to building the plot; unfortunately if I leave them as-is, I get Wrong placement (and/or size) of picture / plot with groupplot of table (... and discontinuity)? (even in a standalone .tex file). Specifically, if the commands execute between {document} and {tikzpicture}, then the extraneous space is generated; I could have the commands in preamble, but then the .tikz file will not be self-contained.

So, I thought I'd collect these commands in a \def subroutine, and have them run inside the {tikzpicture}. Unfortunately, one of those commands is \widthof, which I intended for measuring the width of the text "256" in the tiny font, and wanted to use that to set the x scale of the pgfplot. So I came to this MWE:

% \documentclass{article}
\documentclass{standalone}

\usepackage{calc} %\widthof
\usepackage{pgfplots}
\pgfplotsset{compat=1.5.1}
\usetikzlibrary{pgfplots.groupplots}
\usepackage{pgfplotstable}

\pagecolor{yellow!15}

% \newcommand\prepCmds{
\def\prepCmds{
  \newlength{\smlblwtmp}
  \setlength{\smlblwtmp}{\widthof{\tiny 256}}
  \global\let\smlblwid\smlblwtmp
  \typeout{smlblwid FIRST: \the\smlblwid}
}

% \prepCmds{} % smlblwid FIRST: 10.2085pt

\begin{document}

% \prepCmds{} % smlblwid FIRST: 10.2085pt

\begin{tikzpicture}

  \prepCmds{} % smlblwid FIRST: 0.0pt

  \begin{axis}[
    x=2*\smlblwid,
  ]
    \addplot {x*0.5};
  \end{axis}

\end{tikzpicture}

\end{document}

As it can be seen, only when I call the \prepCmds inside {tikzpicture}, the \widtgof fails and returns 0 (everywhere else, it returns a correct number); when that happens, pdflatex shows this:

PGFPlots warning: The ticklabel anchor cannot be determined, the normal vector 
-(0.0pt,-1.0pt) and the unit y vector (0.0pt,1.00005pt) are almost parallel (ab
s(cos(angle)) = 1.00005pt)!
pgfplots@borderanchor@for@axis 1,2,3: y, 1v0, rectangle

One would say, as expected for x unit of 0 - but it took me hours to debug this so far: among other things, I inserted a \message in the pgfplots source so the arguments of \pgfplots@borderanchor@for@axis are plotted (when the width is not zero, with \prepCmds running elsewhere, the arguments are x, v00, rectangle).

Obviously, all this boils down to \widthof returning 0 inside a {tikzpicture}; now that I know this, I guess I could move just the \widthof calculation out of the subroutine. However, I'd still prefer for the \widthof calculation to be inside the subroutine, for self-containment reasons, so I would like to ask: why is \widthof inside a {tikzpicture} zero; and is there some sort of a trick (maybe "globalize" some tikz intern variables?) that would make \widthof work inside a {tikzpicture} properly?

marked as duplicate by egreg, percusse tikz-pgf Jun 7 '14 at 12:59

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    First of all move \newlength{\smlblwtmp} outside the definition of \prepCmds. About the specific problem: inside a tikzpicture, the current font is set to \nullfont that has no character, so the width you're measuring is zero. – egreg Jun 7 '14 at 12:36
  • Many thanks @egreg - that explains it; if you don't mind posting that as an answer, I'll accept it. Cheers! – sdaau Jun 7 '14 at 12:53
  • 1
    I'd rather close this as a duplicate. – egreg Jun 7 '14 at 12:57
  • 1
    Oh, damn. I have a hammer. please let us know if you want to keep it open. I didn't know that it closes right away – percusse Jun 7 '14 at 13:00
  • @egreg: sure - closure sounds good, the answer is in the comments anyways (as long as the question isn't deleted, I do think alternative formulations can be useful :)) Cheers! – sdaau Jun 7 '14 at 13:01
2

As @egreg mentioned, inside the TikZ environment, in order to keep the non code garbage not printed, \nullfont is applied. So

\tikz{la la laaa. x sdf tgrert}

prints nothing. Here you can also use PGF math function width too without calc but as a stupid side-effect you need to protect the text font switches three times from expansion.

% \documentclass{article}
\documentclass{standalone}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.5.1}
\usetikzlibrary{pgfplots.groupplots}
\pagecolor{yellow!15}

\newlength\smlblwid

\def\prepCmds{
  \pgfmathparse{width("\noexpand\noexpand\noexpand\noexpand\noexpand\noexpand\noexpand\tiny 256")}
  \smlblwid=\pgfmathresult pt
}

\begin{document}

\begin{tikzpicture}

  \prepCmds{}

  \begin{axis}[
    x=2*\smlblwid,
  ]
    \addplot {x*0.5};
  \end{axis}

\end{tikzpicture}

\end{document}

enter image description here

  • 1
    This won't definitely work if the text doesn't contain just ASCII characters and I'm certain you know it. – egreg Jun 7 '14 at 12:57
  • 1
    @egreg Indeed also I think the length calculation is wrong now that I think of it. But it's good to get rid of the overhead for simple cases – percusse Jun 7 '14 at 12:58
  • Still, I like a lot having an alternative - wasn't aware that there was an alternative width I could have used... – sdaau Jun 7 '14 at 12:59

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