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.

Consider the following code (taken from Jake's answer) and focus on the variable of the function to be plotted.

\documentclass[border=5pt,tikz]{standalone}

\begin{document}
\begin{tikzpicture}
    \draw [domain=0:50,variable=\t,smooth,samples=500]
        plot ({\t r}: {1+2*exp(-\t/10)});
\end{tikzpicture}
\end{document}

My question is quite simple, why must the variable be a macro (\t in this case) rather than just a letter (for example t) or a word (for example theta) as I think we usually use a letter when using a graphics calculator or Computer Algebra Systems? PSTricks, for example, also does not need a macro when plotting. In PSTricks, \psplot[algebraic]{-4}{4}{x^2-5*x+6} where x is the independent variable and it does not need to be a macro \x.

The relevant case of using a macro is when we use a loop such as \foreach \t in {1,...,2}{<do with \t>}. But I don't think plotting needs such an iterating variable \t exposed to the users. Hopefully you understand what I don't understand.

You might think of why I made a fuss about it. Because the macro makes the function expression no longer natural, elegant, beautiful, simple, etc. For example, t^2-5*t+6 becomes \t*\t-5*\t+6 which is not natural and of course the existence of \ consumes more keystrokes.

Do you think there is a benefit of the current syntax where the independent variable must be a macro?

share|improve this question
    
Because t can be function name (as sin, exp...). –  Paul Gaborit Nov 8 '13 at 6:22
    
@PaulGaborit Yes, but so can any name you could use as a PGFmath function. The \pgfmathdeclarefunction macro checks whether another PGFmath function with the same name already exists and throws an error in that case. Even worse, the macro you use could be an already used macro and would get overwritten (locally but still). –  Qrrbrbirlbel Nov 8 '13 at 6:33
    
@Qrrbrbirlbel In the function expression, all PGFmath functions are potentially useful while any already used macro is rarely used. –  Paul Gaborit Nov 8 '13 at 6:52
1  
It depends on the tikz/pgf parser of course but your pstricks example of x sin not needing \x is misleading (or not relevant, or something). That is PostScript syntax and to refer to the value stored in x in PostScript the syntax is x not \x. –  David Carlisle Nov 8 '13 at 9:27
2  
@Marienplatz indeed, although the conversion is carried out at the postscript level. If you are interested in seeing this feature in PGF (rather than just trying to highlight a perceived failing in the package) you are welcome to file a feature request here. –  Mark Wibrow Nov 8 '13 at 15:02

3 Answers 3

up vote 11 down vote accepted

When pgfmath parser was written, the main aim was to provide consistent and slightly more versatile mathematical operations than the calc package (which used to do all the calculations) without the overhead of the fp package. Also the integration with \foreach variables was important as well (as been suggested above).

So, every expression given to the pgfmath parser is \edef'ed immediately prior to parsing. This means that in most cases (unless you do something clever with \noexpand inside double quotes) that

  • any unexpanded tokens are TeX registers
  • the parser does not have to worry about checking whether tokens are expandable

As things stand it is possible to define a function which can stand for a plotting variable (as has been shown above). This is, to my knowledge, the only way of achieving the OPs requirements. But (as has also already been pointed out) parsing a number is quicker than parsing/evaluating a function.

As a "side note", I genuinely intended pgfmath to be a temporary fix for mathematical operations inPGF and thought that when luatex came along "proper" programmers would jump in and sort things out. Sadly that hasn't happened.

share|improve this answer
    
How many times is the parsing performed? Once before start plotting or N times (one parsing per iteration) where N represents the plot points. –  cyanide-based food Nov 8 '13 at 8:09
    
Since calculations cannot be left to the renderer and have to be performed by the package, parsing occurs at least once, and most probably twice per point (quite often more) depending on calculations required by the plot handler. –  Mark Wibrow Nov 8 '13 at 8:19

Why? I don’t know.

Though, TikZ doesn’t do anything else but to iterate over the domain. When TikZ plots a function it uses the PGF macro \pgfplotfunction for this. In our case it is called with something like (the third parameter is not correct but this is essentially how you would do this in PGF)

\pgfplotfunction{\t}{0, 0.10019, ..., 50}{\pgfpointpolar{\t r}{1+2*exp(-\t/10)}

In the definition of \pgfplotfunction we find something like

% Initialize plotting
\foreach #1 in {#2}{
   % parse #3, extract x and y and sent it to the plotter
}
% Do the actual plotting

Here’s a way around it by defining a PGFmath variable that simply expands to the variable used by the plotter. To not overwrite any already defined macros like \t or \theta (which could be used by a node on the path), I “hid” the actual variable name in a m@cro.

\tikzset{
  variable*/.style={
    declare function={#1=\tikz@plot@var;},
    variable=\tikz@plot@var}}

You can now say variable*=theta and then use theta instead of \t in the function.

I have added a “fast” version in the code below because our variable is already calculated by the \foreach loop and doesn’t need additional parsing or evaluating. Thus, I copy the value of the iterator directly to \pgfmathresult.


Note that if you plot with gnuplot (an external tool to TeX and TikZ) by using the function plot operator as in

\draw plot[parametric, domain=0:50, samples=500, smooth]
        function {cos(t)*(1+2*exp(-t/10)), sin(t)*(1+2*exp(-t/10))};

you need to use the variables x and, for parametric plots, t.

Code

\documentclass[border=5pt,tikz]{standalone}
\makeatletter
\tikzset{variable*/.code=\pgfmathdeclarefunction{#1}{0}{\let\pgfmathresult\tikz@plot@var}%
                         \def\tikz@plot@var{\tikz@plot@var}}
\makeatother
\begin{document}
\begin{tikzpicture}
    \draw [domain=0:50,variable*=theta,smooth,samples=500]
        plot (theta r: {1 + 2 * exp( -theta / 10)});
\end{tikzpicture}
\end{document}
share|improve this answer
    
By the way, is there any advantage of the current mechanism where the variable must be a macro? –  cyanide-based food Nov 8 '13 at 4:59
    
@Marienplatz It probably is faster (depending on how PGFmath parses things but I guess that parsing a number is faster than checking for a possible function name (and possible options)). Using \pgfmathdeclarefunction also adds a few other auxiliary macros and itself takes time. — Note that I just realized that there is no need for yet another macro, we can just use \tikz@plot@var itself. :) –  Qrrbrbirlbel Nov 8 '13 at 5:31
    
@Marienplatz On that topic, it seems that you can get away with \pgfmath@namedef{pgfmath@function@#1}{\let\pgfmathresult\tikz@plot@var}\pgfmath‌​@namedef{pgfmath@operation@#1@arity}{0} reducing the needed macros to two and also only needing two \defs instead of a lot of the parsing the \pgfmathdeclarefunction does. But this will probably break somewhere. –  Qrrbrbirlbel Nov 8 '13 at 5:35

Not that I recommend it at all, as the nice key=value syntax is lost, but it is possible to do a bit of the job done by TikZ and avoid having a macro for the variable in plots. But one still needs a macro, now for the expression giving the plotted points. I tried without but it appears that after coordinates one needs something completely expandable, so I could not use \xintFor there.

The macros \Sample, \SamplE and \SampleFit are a bit undecipherable, what they do is to compute the #1 which will be used by the macro \PointMacro (name arbitrary) corresponding to the actual plot. The #1 will be a fixed point number with 4 digits after decimal mark.

\documentclass[border=5pt,tikz]{standalone}
\usepackage{xintfrac}

% \Sample {N}\pointmacro {start:end}
% it returns expandably the N points from  N equispaced samples starting with
% start and ending with end.
% \pointmacro (name arbitrary) 
% should be a one-parameter macro which returns a point
% as recognized by tikz (such as (x,y), or (angle:radius))
% example \def\macro #1 {(#1, {(#1)^2})}
% see examples below

\def\Sample #1#2#3{\SamplE {#1}#2#3;}

\def\SamplE #1#2#3:#4;{\expandafter\xintApplyUnbraced\expandafter
     {\expandafter\SampleFit\expandafter #2\expandafter
       {\romannumeral0\xintdiv{\xintSub{#4}{#3}}{\xintDec{#1}}}{#3}}
     {\xintSeq{0}{#1-1}}}

\def\SampleFit #1#2#3#4{\expandafter #1\expandafter{\romannumeral0%
                       \xinttrunc {4}{\xintAdd{#3}{\xintMul{#2}{#4}}}}}

\begin{document}    
\tikzset {x=.5cm, y=.5cm}

\begin{tikzpicture}
    \def\ParabolaPoint #1{(#1, {(#1)^2})}% negative #1 within parentheses!
    \draw [smooth] plot coordinates {\Sample {25}\ParabolaPoint {-2:2}};
\end{tikzpicture}

\begin{tikzpicture}
    \def\CubicPoint #1{(#1, {(#1)^3})}
    \draw [smooth] plot coordinates {\Sample {25}\CubicPoint {-1.25:1.25}};
\end{tikzpicture}

\begin{tikzpicture}
    \def\SpiralPoint #1{({#1 r}: {1+2*exp(-#1/10)})}
    \draw [smooth] plot coordinates {\Sample {200}\SpiralPoint {0:50}};
\end{tikzpicture}

\end{document}

parabolacubicspiral

share|improve this answer
    
\xintSeq {0}{#1-1} in the \SamplE code generates {0}{1}{2}..{N} with N=#1-1. If N is too large (around 5000 on my installation) there is a problem with the input stack. This is explained in the xint documentation, and the fix is to use \xintSeq [1]{0}{#1-1} which does the same in an input stack compatible way. So if one wants 5000 sample points one should use a variant of \SampleE where a [1] has been inserted after \xintSeq. –  jfbu Nov 8 '13 at 11:07

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.