Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to make a PGF plot which, besides normal 2D graph, includes scalar field, that is values of the 2D function in various positions of the 2D graph.

Of course, I tried to do that using \foreach command. First I learned from stackexchange that running loops requires some additional tweak using \edef. But still I do not know how to actually calculate function of two parameters. \pgfmathparse simply does not work. The example below does not sum \i and \j but simply write them down one next to other.

Maybe my ideas are completely wrong and there is much easier method to draw scalar fields. Can someone help me on this?

Regards, Marko.

\documentclass{minimal}
\usepackage{tikz,pgfplots}

\begin{document}
\begin{tikzpicture}
\begin{axis}[domain=-2.5:2.5,view={0}{90},axis background/.style={fill=white},]
\addplot {x^2};

\foreach \i in {-2.4,-1.2,...,2.4}
  {\foreach \j in {-2.4,-1.2,...,2.4}
    {\edef\temp{\noexpand \node at (axis cs:\i,\j) {\pgfmathparse{\i+\j}\pgfmathresult};}
    \temp}}

\end{axis}
\end{tikzpicture}
\end{document}
share|improve this question
1  
I can't test now but please check the Section 8 of the manual for commands like \pgfplotsforeachungrouped for different types of foreach commands. –  percusse Apr 7 '12 at 18:28
    
Honestly, I understand almost nothing in this section. I've replaced \foreach with \pgfplotsforeachungrouped and \pgfmathparse still does not work. –  Pygmalion Apr 7 '12 at 19:08
    
@Marko if you supply your code with \pgfmathparse we can probably help you with the error there. A typical error is that you have to use \pgfmathresult afterwards: \pgfmathparse{1+2}\pgfmathresult -> 3. –  zeroth Apr 7 '12 at 20:31
    
I did so above. If you replace \pgfmathparse{\i+\j}\pgfmathresult with, say, 2, it works fine. –  Pygmalion Apr 8 '12 at 7:05

1 Answer 1

up vote 7 down vote accepted

This is an expansion problem.

That said, I can give you an introduction into the expansion control of TeX - which is what you are doing here.

While I write this, I have two other questions in mind: the first is asking myself if there is some kind of feature request behind all that. Perhaps the whole handling of programmatical loops inside of an axis needs to be thought through by an expert (i.e. by me as author of pgfplots). Obviously, the special requirements of the axis cause confusion (and you are not the first to suffer from it).

The second is: are you interested in learning TeX to be able to script things? Loops are "scripts". And, unfortunately, require special handling inside of an axis as you already knew. If so, my answer below might be adequate.

If you are not really interested in this sort of scripting (and you are only doing it for this elementary problem at hand), then I might point out the nodes near coords feature, combined with an \addplot3 table and/or \addplot3 {<expression>} might do what you need - without resorting to scripts, only by means of high-level methods.

I am coming back to your question as such now:

SOLUTION 1

Since your loops actually only add annotations and no plots, you can postpone the complete processing to the visualization phase.

This is what happens if your write \draw or \node inside of an axis: pgfplots automatically collects the (unexpanded) arguments up to the next semicolon ; and postpones the execution until the visualization phase.

The \edef construction is necessary to mix visualization phase and survey phase of the axis (survey == involves plots where limits need to be updated etc).

Pgfplots offers a simple approach to postpone things to the visualization phase:

\pgfplotsextra{<material which is postponed to the visualization phase>} .

Within this material, you can use \foreach as in TikZ - without all that \edef, \noexpand, etc:

\pgfplotsextra{
\foreach \i in {-2.4,-1.2,...,2.4}
  {\foreach \j in {-2.4,-1.2,...,2.4}
    {\node at (axis cs:\i,\j) {\pgfmathparse{\i+\j}\pgfmathprintnumber{\pgfmathresult}};}
  }
}

Note that I added \pgfmathprintnumber here.

SOLUTION 2

To fix your text, get an answer for the immediate question, and learn something about TeX scripting, proceed as follows:

The solution is to add \noexpand in front of all macros inside of your \edef construct -- unless you explicitly know that the value should be expanded immediately.

The correct solution is

\foreach \i in {-2.4,-1.2,...,2.4}
  {\foreach \j in {-2.4,-1.2,...,2.4}
    {\edef\temp{\noexpand \node at (axis cs:\i,\j) {\noexpand\pgfmathparse{\i+\j}\noexpand\pgfmathresult};}
    \temp}}

And here is the explanation:

  • \edef means "expanded definition". It defines \temp to contain the complete expansion of everything that follows - where "complete expansion" means to expand everything until it cannot be expanded further.

  • In TeX, there is a distinction between "expandable" and "unexpandable" material. Learning to decide which is what seems difficult and technical - but there is a very simple heuristics which is true in 99% of the cases: if something is "executable", you can be sure that it cannot be expanded. If something "simply contains a value", you can almost surely expand it.

Here, \node and \pgfmathparse are both executable. Consequently, they cannot be expanded - and need to be protected from expansion. Omitting the protection will cause unanticipated and unpredictable results (as in your case).

On the contrary, \i and \j are single values - and can be expanded (that was the whole idea here).

  • "Protecting something from expansion inside an \edef" can be accomplished by prefixing the macro in question with \noexpand.

that explains the \noexpand\node and \noexpand\pgfmathparse.

  • Finally, you have to add \noexpand\pgfmathresult as well -- because the \pgfmathresult should be the result of your \pgfmathparse, and not the current value of \pgfmathresult.

Ah - you may want to consider using \noexpand\pgfmathprintnumber{\noexpand\pgfmathresult} here as in Solution 1.

See also http://pgfplots.sourceforge.net/TeX-programming-notes.pdf for details on TeX programming.

share|improve this answer
    
What I really needed was solution 1. But I'll bookmark your solution 2 in case I'll need in sometimes in future. –  Pygmalion Apr 8 '12 at 9:48
    
Actually, I also have a feature request that might not be too hard to implement. It would be really nice if quiver would have option to show different vector sizes as different vector thicknesses and not different vector lengths. Very useful if one wants to draw a vector field with with huge vector size span. Similar method is implemented by meteorologists, where number of ticks at the end of line represents wind strength. –  Pygmalion Apr 8 '12 at 19:12

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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