9

The following approach to Riemann Sums first draws an arbitrary curve (which may later be tweaked), then forms rectangles based upon intersections. Unfortunately, the filled rectangles hide portions of the curve. The path and rectangles, however, can not be interchanged since the rectangles depend upon the path coordinates. How can this problem be avoided without dramatically altering the approach?

Ps. I tried simply redrawing the curve after the rectangles but, for some reason, I cannot draw ANYTHING beyond the given code without prompting an error message. Something is wrong.

\documentclass{article}

\usepackage{tikz} 
\usetikzlibrary{intersections}

\begin{document}

\begin{tikzpicture}
%axis 
\draw (-.5,0) -- (6.5,0);  

%curve  
\draw[yshift=1cm,name path=curve] (-.5,0) %vertically shiftable
    to[out=70,in=180] (.7,1.5)
    to[out=0,in=180] (2,.5)
    to[out=0,in=180] (4.5,2.5)
    to[out=0,in=160] (6.5,1);

%rectangles
\foreach \x in {0,1,2,5}{
    \path[name path=line \x] (\x,0) -- (\x,4);
    \path[name intersections={of=curve and line \x, by={isect \x}}];    
    \draw[fill=gray!50] (isect \x) rectangle (\x+1,0);
    \draw[fill] (isect \x) circle [radius=2pt];
    }
\end{tikzpicture}

\end{document}

2 Answers2

10

Using the code from Calling a previously named path in tikz, we can define the curve before drawing the rectangles but delay its rendering until afterwards.

\documentclass{article}
%\url{https://tex.stackexchange.com/q/150486/86}
\usepackage{tikz} 
\usetikzlibrary{intersections}

\makeatletter
\tikzset{
  use path for main/.code={%
    \tikz@addmode{%
      \expandafter\pgfsyssoftpath@setcurrentpath\csname tikz@intersect@path@name@#1\endcsname
    }%
  },
  use path for actions/.code={%
    \expandafter\def\expandafter\tikz@preactions\expandafter{\tikz@preactions\expandafter\let\expandafter\tikz@actions@path\csname tikz@intersect@path@name@#1\endcsname}%
  },
  use path/.style={%
    use path for main=#1,
    use path for actions=#1,
  }
}
\makeatother


\begin{document}

\begin{tikzpicture}
%axis 
\draw (-.5,0) -- (6.5,0);  

%curve  
\path[yshift=1cm,name path=curve] (-.5,0) %vertically shiftable
    to[out=70,in=180] (.7,1.5)
    to[out=0,in=180] (2,.5)
    to[out=0,in=180] (4.5,2.5)
    to[out=0,in=160] (6.5,1);

%rectangles
\foreach \x in {0,1,2,5}{
    \path[name path=line \x] (\x,0) -- (\x,4);
    \path[name intersections={of=curve and line \x, by={isect \x}}];    
    \draw[fill=gray!50] (isect \x) rectangle (\x+1,0);
    \draw[fill] (isect \x) circle [radius=2pt];
    }

\draw[use path=curve];

\end{tikzpicture}

\end{document}

Riemann sums

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
9

I don't know what causes the problem with not being able to draw after that \foreach, but a different way is to use the backgrounds library to place the rectangles on the bottom layer.

enter image description here

\documentclass{article}

\usepackage{tikz} 
\usetikzlibrary{intersections,backgrounds}

\begin{document}

\begin{tikzpicture}
%axis 
\draw (-.5,0) -- (6.5,0);  

%curve  
\draw[yshift=1cm,name path=curve] (-.5,0) %vertically shiftable
    to[out=70,in=180] (.7,1.5)
    to[out=0,in=180] (2,.5)
    to[out=0,in=180] (4.5,2.5)
    to[out=0,in=160] (6.5,1);

%rectangles
\begin{scope}[on background layer]
\foreach \x in {0,1,2,5}{
    \path[name path=line \x] (\x,0) -- (\x,4);
    \path[name intersections={of=curve and line \x, by={isect \x}}];    
    \draw[fill=gray!50] (isect \x) rectangle (\x+1,0);
    \draw[fill] (isect \x) circle [radius=2pt];
    }
\end{scope}    
\end{tikzpicture}
\end{document}
Torbjørn T.
  • 206,688