11

Despite having read answers to 4-5 relate questions, I still can't get why my code does not compile. Here it is:

\documentclass[11pt,twoside]{book}
\usepackage[paperheight=24cm, paperwidth=35cm, margin=0pt, %
voffset=-50cm, hoffset=-1.4cm]{geometry}
\usepackage{tikz}

\usetikzlibrary{calc}

\begin{document}

\pagestyle{empty}

\begin{figure}[!h]
\centering\begin{tikzpicture}[xscale=1,yscale=1]
\draw[very thick,yellow,samples=500,domain=-6*pi:6*pi]
plot (\x, {cos((3*\x r)+pi/2)+\x*sin(3*\x r)});
\draw[very thick,orange,samples=500,domain=-6*pi:6*pi]
plot (\x, {-0.25*(pow(\x,2)*cos(\x r)-\x*sin(\x r))});
\draw[very thick,green,samples=500,domain=-6*pi:6*pi]
plot (\x, {cos(\x r)+\x});
\draw[very thick,magenta,samples=500,domain=-6*pi:6*pi]%%          error!
plot (\x, {0.5*(pow(10,-11)*exp(-3*\x)-cos(\x r)+3*sin(\x r))});%% error!
\draw[very thick,blue,samples=500,domain=-6*pi:6*pi]%%             error!
plot (\x, {pow(10,-15)*exp(3*\x)});%%                              error!
\end{tikzpicture}
\end{figure}

\end{document}

The latest two of five plots - as I showed in comments - are driving me mad. Please notice the massive voffset too. Is it related? Obviously I tried several local modifications (e.g. radiants, etc.). This was just a test but now I'm seriously curious.

  • 2
    Welcome to TeX.SX! The value of the exponential function at 6\pi is way more than the fixed-point number system used by TeX can handle. You should try using the PGF floating-point library (fpu). – jubobs Apr 10 '14 at 19:08
  • Great, thanks, I see. How do I recall it? – MattAllegro Apr 10 '14 at 19:23
  • 1
    Actually, this is what the PGF/Tikz manual says about fpu: Subsection 36.1 Note that the library has not really been tested together with any drawing operations. It should be used to work with arbitrary input data which is then transformed somehow into PGF precision. The pgfplots package is your best bet (see percusse's answer). – jubobs Apr 10 '14 at 19:59
  • 1
    Notice that for the 4th function, 10^(-11)*exp(-3x) triggers a value of… 36205484966053 for x = -6pi. Even with fpu, it will be difficult to represent that range of value with yscale = 1! – Franck Pastor Apr 10 '14 at 20:09
4

Percusse has answered accordingly to the question. (I think his answer should be marked as "accepted", by the way). I took the liberty to propose a MetaPost solution, however.

Until quite recently, this kind of function drawing would have been impossible to do with MetaPost, since it was based only on quite limited fixed-point numerics. But since its version 1.8 the user can switch to floating-point numerics at will, by setting the internal variable numbersystem to double. It's still a bit rough around the edges (the default units has not yet been adapted, for example) but it's quite functional, and I couldn't resist to use it for this problem. The following program makes use of LuaLaTeX and its luamplib package as a very convenient interface to MetaPost. It calls the Metafun format of MetaPost, which defines the necessary auxiliary functions (cos, sin, exp…)

\documentclass[11pt]{standalone}
\usepackage{unicode-math}
\usepackage{luamplib}
  \mplibsetformat{metafun}
  \mplibtextextlabel{enable}
  \mplibnumbersystem{double}
\begin{document}
\begin{mplibcode}
  input mpcolornames;
  % pi, cm (and mm) as accurate as possible 
  %(defaults settings are too inaccurate: pi = 3.14159265, cm = 28.34645)
  pi:= 3.141592653589793; 
  cm := 3600/127; mm := 360/127; 
  % Unit lengths
  u = .5cm; v = mm; 
  % Graphs boundaries
  xmin = -6pi; xmax = -xmin; xsep = (xmax - xmin)/1000; ymin = -80; ymax = 100;
  % Axes settings
  Xmin = -20; Xmax = -Xmin; Ymin = -85; Ymax = 110;
  % Macro building the graph of a given function f
  vardef graph_of_function (suffix f) (expr xmin, xmax, xsep) =
    for x = xmin step xsep until xmax: (x, f(x)) .. endfor (xmax, f(xmax))
  enddef ;
  % Functions to be graphed
  vardef e(expr x) = cos(pi/2 + 3x) + x*sin 3x enddef;
  vardef f(expr x) = -.25(x**2)*cos x - x*sin x enddef;
  vardef g(expr x) = x + cos x enddef;
  vardef h(expr x) = .5(-cos x + 3sin x + 1e-11exp -3x) enddef;
  vardef i(expr x) = 1e-15exp 3x enddef;
  %
  beginfig(0);
    % Drawing of the given functions
    pickup pencircle scaled 1.25bp;
    draw (graph_of_function(e)(xmin, xmax, xsep)) xyscaled (u, v) withcolor yellow;
    draw (graph_of_function(f)(xmin, xmax, xsep)) xyscaled (u, v) withcolor Orange;
    draw (graph_of_function(g)(xmin, xmax, xsep)) xyscaled (u, v) withcolor green;
    draw (graph_of_function(h)(xmin, xmax, xsep)) xyscaled (u, v) withcolor magenta;
    draw (graph_of_function(i)(xmin, xmax, xsep)) xyscaled (u, v) withcolor blue;
    % Clipping
    clip currentpicture to 
      ((xmin, ymin) -- (xmax, ymin) -- (xmax, ymax) -- (xmin, ymax) -- cycle) 
        xyscaled (u, v);
    % Axes and labels
    pickup pencircle scaled .5bp;
    drawarrow (Xmin*u, 0) -- (Xmax*u, 0); drawarrow (0, Ymin*v) -- (0, Ymax*v);
    label.llft("$O$", origin); 
    label.lft("$y$", (0, Ymax*v)); label.bot("$x$", (Xmax*u, 0));
    % Marking…
    labeloffset := 6bp;
    % … on the horizontal axis
    draw (u*pi, -3bp) -- (u*pi, 3bp); draw (-u*pi, -3bp) -- (-u*pi, 3bp);
    label.bot("$\pi$", (pi*u, 0)); label.bot("$-\pi$", (-pi*u, 0));
    for i = 2 upto 6:
      draw (i*pi*u, -3bp)-- (i*pi*u, 3bp); 
      label.bot("$" & decimal i & "\pi$", (i*pi*u, 0));
      draw (-i*pi*u, -3bp)-- (-i*pi*u, 3bp); 
      label.bot("$" & decimal -i & "\pi$", (-i*pi*u, 0));
    endfor;
    % … on the vertical axis
    for i = 20 step 20 until 80:
      label.lft("$" & decimal i & "$", (0, i*v));
      label.lft("$" & decimal -i & "$", (0, -i*v));
      draw (-3bp, i*v) -- (3bp, i*v);
      draw (-3bp, -i*v) -- (3bp, -i*v);
    endfor;
    label.lft("$100$", (0, 100v)); draw (-3bp, 100v) -- (3bp, 100v);
    % Preventing possible cropping of labels at the figure boundaries
    setbounds currentpicture to boundingbox currentpicture enlarged .5cm;
  endfig;
\end{mplibcode}
\end{document}

enter image description here

  • Wow! This looks very much like what I wanted to achieve, thank you all very much! – MattAllegro Apr 12 '14 at 16:33
  • One last thing i don't get is the following. Going back to the comment added by fpast, why my original - and intuitive - code cannot plot exponentials values around y=60 (that would be enough for me) while it plots the orange sinusoid at y=60? Anyway you've been all very welcome, I'll have a lot to study now! – MattAllegro Apr 12 '14 at 16:59
  • If you want to stick to tikz without using floating-point numerics, the interval must be restricted. Does it break tikz if you draw it, say, on the [-3pi,3pi] interval? – Franck Pastor Apr 13 '14 at 6:07
  • in the caso of plot (\x, {pow(10,-15)*exp(3*\x)});, I can use -6pi as lower bound of my domain but I get the usual error if I choose an upper bound greater than 1.03pi. How many times I thought "with 3pi or similar it should work"... – MattAllegro Apr 13 '14 at 9:47
  • 1
    It's normal that the orange one is correctly rendered: tikzhas no problem for computing the terms of that function, nor for making their multiplication. For example, x^2 is not too big in the range of value -3p…3pi. Whereas exp(3x), which must first be computed before being multiplied by 10^-11(which is very small and therefore must be seen by tikz als equal to 0!) becomes fast much, much bigger than x^2. Too big for tikz and its default fixed-point numerics thus. – Franck Pastor Apr 13 '14 at 13:40
15

Just simply use pgfplots. TikZ in this case is hopeless to deal with such precision. In fact, I just copy pasted and replaced commands. Also adjusted the y domain to make the plots seen.

\documentclass[11pt,twoside]{book}
\usepackage{pgfplots}

\begin{document}

\begin{figure}
\centering
\begin{tikzpicture}
\begin{axis}[samples=500,domain=-6*pi:6*pi,restrict y to domain =-20:100]
\addplot[very thick,yellow ]plot (\x, {cos((3*\x r)+pi/2)+\x*sin(3*\x r)});
\addplot[very thick,orange ]plot (\x, {-0.25*(pow(\x,2)*cos(\x r)-\x*sin(\x r))});
\addplot[very thick,green  ]plot (\x, {cos(\x r)+\x});
\addplot[very thick,magenta] plot (\x, {0.5*(pow(10,-11)*exp(-3*\x)-cos(\x r)+3*sin(\x r))});
\addplot[very thick,blue   ] plot (\x, {pow(10,-15)*exp(3*\x)});
\end{axis}
\end{tikzpicture}
\end{figure}

\end{document}

enter image description here

1

I was really forgetting to post how I finally handled it: functions domains modified where necessary (see %% error! in the question code).

\documentclass[11pt,twoside]{book}
\usepackage[paperheight=24cm, paperwidth=35cm, margin=0pt, %
    voffset=-140cm, hoffset=-1.4cm]{geometry}
\usepackage{tikz}

\usetikzlibrary{calc}

\begin{document}

\pagestyle{empty}

\begin{figure}[!h]
\centering\begin{tikzpicture}%[xscale=1,yscale=1]
\draw[very thick,yellow,samples=500,domain=-6*pi:6*pi]
plot (\x, {cos((3*\x r)+pi/2)+\x*sin(3*\x r)});

\draw[very thick,orange,samples=500,domain=-6*pi:6*pi]
plot (\x, {-0.25*(pow(\x,2)*cos(\x r)-\x*sin(\x r))});

\draw[very thick,green,samples=500,domain=-6*pi:6*pi]
plot (\x, {cos(\x r)+\x});

\draw[very thick,magenta,samples=500,domain=-pi:6*pi]
plot (\x, {0.5*(pow(10,-2)*exp(-3*\x)-cos(\x r)+3*sin(\x r))});%

\draw[very thick,blue,samples=500,domain=-6*pi:.8*pi]
plot (\x+1, {exp(2*\x)});%
\end{tikzpicture}
\end{figure}

\end{document}

output

By the way I think this could be made even better by using standalone documentclass and TikZ command clip. I'll post an update next time I must make a plot picture for a full book sleeve!

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.