5

I'm trying to write a loop to plot a rectangle showing the Midpoint Rule using pgfplots, but cannot evaluate the function to draw it. (around the end of code). Actual code isn't compiling.

\documentclass{article}
\usepackage{pgfplots} 
\begin{document}
\pgfplotsset{
    integral axis/.style={
        axis lines=middle,
        enlarge y limits=upper,
        axis equal image, width=12cm,
        xlabel=$x$, ylabel=$y$,
        ytick=\empty,
        xticklabel style={font=\small, text height=1.5ex, anchor=north},
        samples=100
    },
    integral/.style={
            domain=2:8,
            samples=7
    },
    integral fill/.style={
            integral,
            draw=none, fill=#1,
            %on layer=axis background
    },
    integral fill/.default=cyan!10,
    integral line/.style={
            integral,
            very thick,
            draw=#1
    },
    integral line/.default=black
}


\begin{tikzpicture}[
    % The function that is used for all the plots
    declare function={f=x/5-cos(deg(x*1.85))/2+2;}
]
\begin{axis}[
    integral axis,
    ymin=0,
    xmin=0.75, xmax=9.25,
    domain=1.5:8.5,
    xtick={2,2.5,3,3.5,...,8},
    xticklabels={$x_0$, $x_{1/2}$, $x_1$,$x_{3/2}$,$x_2$,$x_{5/2}$,$x_3$,,,,$x_{N-1}$,$x_{N-\frac{1}{2}}$,$x_N$},
    axis on top
]
% The filled area under the approximate integral
\addplot [integral fill=cyan!15] {f} \closedcycle;

% The highlighted segment
%\addplot [integral fill=cyan!35, domain=6:7, samples=2] {f} \closedcycle;

% The function
\addplot [very thick, cyan!75!blue] {f} node [anchor=south] {$y=f(x)$};

% The approximate integral
\addplot [integral line=black] {f};

% The vertical lines between the segments
\addplot [integral, ycomb] {f};

% Issue is here.
\foreach \i in {2.5,3.5,...,7.5} {
    \pgfmathsetmacro\y{\f \i};
    \draw (\i-.5,\y) rectangle (\i+.5,0);
}

\end{axis}
\end{tikzpicture}

\end{document}

1 Answer 1

10

Pgfplots comes with its own foreach version, which you may want to use here. Notice that you did not specify a version. In older versions of pgfplots you need to add axis cs: to the coordinates in the loop. I adjusted your function such that it is really a function of a variable, otherwise you cannot use it in the \draw commands

\documentclass{article}
\usepackage{pgfplots} 
\begin{document}
\pgfplotsset{compat=1.16,
    integral axis/.style={
        axis lines=middle,
        enlarge y limits=upper,
        axis equal image, width=12cm,
        xlabel=$x$, ylabel=$y$,
        ytick=\empty,
        xticklabel style={font=\small, text height=1.5ex, anchor=north},
        samples=100
    },
    integral/.style={
            domain=2:8,
            samples=7
    },
    integral fill/.style={
            integral,
            draw=none, fill=#1,
            %on layer=axis background
    },
    integral fill/.default=cyan!10,
    integral line/.style={
            integral,
            very thick,
            draw=#1
    },
    integral line/.default=black
}


\begin{tikzpicture}[
    % The function that is used for all the plots
    declare function={f(\x)=\x/5-cos(deg(\x*1.85))/2+2;}
]
\begin{axis}[
    integral axis,
    ymin=0,
    xmin=0.75, xmax=9.25,
    domain=1.5:8.5,
    xtick={2,2.5,3,3.5,...,8},
    xticklabels={$x_0$, $x_{1/2}$, $x_1$,$x_{3/2}$,$x_2$,$x_{5/2}$,$x_3$,,,,$x_{N-1}$,$x_{N-\frac{1}{2}}$,$x_N$},
    axis on top
]
% The filled area under the approximate integral
\addplot [integral fill=cyan!15] {f(x)} \closedcycle;

% The highlighted segment
%\addplot [integral fill=cyan!35, domain=6:7, samples=2] {f} \closedcycle;

% The function
\addplot [very thick, cyan!75!blue] {f(x)} node [anchor=south] {$y=f(x)$};

% The approximate integral
\addplot [integral line=black] {f(x)};

% The vertical lines between the segments
\addplot [integral, ycomb] {f(x)};
% Issue is here.

\pgfplotsinvokeforeach{2.5,3.5,...,7.5}{
    \draw[thick,blue] (#1-0.5,{f(#1)}) rectangle({#1+.5},0);
}
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

Of course, you could plot these bars also with a bar plot. That is, you could replace the loop by

\addplot [blue,thick,ybar,bar width=1,samples at={2.5,3.5,...,7.5}] {f(x)};
3
  • 1
    Mr @marmot, thank you one more time. Just for curiosity, is possible to add some discrete evaluated points, lets say in f(x), at some sample positions without to add a line that connects each sampled value?
    – Lin
    Sep 10, 2018 at 4:37
  • 1
    found: only marks.
    – Lin
    Sep 10, 2018 at 4:39
  • @Lin Yes, that's how this can be done. (I'm already in hibernation mode. ;-)
    – user121799
    Sep 10, 2018 at 6:50

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.