Automate Derivative Representation in TikZ

tikz-pgf

I am to begin to write some lecture notes for my students and I will have to do multiple diagrams like the one shown below to represent the simple notion of derivatives graphically. The problem I face is to find a way to automate the creation of such figures. For example, what am looking for is:

  1. Define a function f(x) (in TikZ of course)
  2. Declare the x-coordinates of two points, say x1 and x2. Now these two coordinates can be used to calculate their corresponding y coordinates and the distances shown in the triangle.

Thus am looking for something like, \derivative{x*x}{x1}{x2}. I don't know how the domain can be incorporated but I guess that can be done later.

\documentclass[letterpaper]{article}
\usepackage{fullpage}
\usepackage{amsmath,amssymb,enumitem}
\usepackage[dvipsnames]{xcolor}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows}

\pdfpageheight\paperheight
\pdfpagewidth\paperwidth
\parindent0pt

\begin{document}
\begin{tikzpicture}[line cap=round,line join=round,>=stealth',x=1.0cm,y=1.0cm,domain=-0.5:2.25]
\draw[->,color=black] (-1,0) -- (4,0);
\foreach \x in {1,2,3}
\draw[shift={(\x,0)},color=black] (0pt,2pt) -- (0pt,-2pt) node[below] {\footnotesize $\x$};
\draw[color=black] (4,0) node [right] { $x$};
\draw[->,color=black] (0,-1) -- (0,5);
\foreach \y in {1,2,3,4}
\draw[shift={(0,\y)},color=black] (2pt,0pt) -- (-2pt,0pt) node[left] {\footnotesize $\y$};
\draw[color=black] (0,5) node [above] { $y$};
\draw[color=red,<->] plot[id=quad] function{x*x} node[right] {$f(x) =x^2$};
\fill[black] (0.5,0.25) circle (1.25pt);
\fill[black] (1.5,2.25) circle (1.25pt);
\draw (0.5,0.25)--(1.5,2.25)--(1.5,0.25)--cycle;
\draw[|-|,yshift=-0.25cm] (0.5,0.25)--(1.5,0.25);
\draw[yshift=-0.25cm](1,0.25) node[fill=white] {1};
\draw[|-|,xshift=0.25cm] (1.5,0.25)--(1.5,2.25);
\draw[xshift=0.25cm] (1.5,1.25) node [fill=white] {2};
\end{tikzpicture}
\end{document}

Image of the result: enter image description here

Best Answer

You can use pgfplots for this. I've written a new macro \derivative{<pgfmath function>}{<label>}{<x1>}{<x2>}{<point legend>} that can be used inside a pgfplots axis. It draws a plot of the function, which is specified using pgfmath syntax as a function of \x, and a straight line connecting the function points at two specified x values. It also adds a label to the plot, which is specified using the second argument, and a legend listing the two points, which has to be supplied in the fifth argument. You can influence the legend position and appearance using point legend/.style={<options>} in the axis options, and the position and appearance of the point labels using point 1/.style and point 2/.style.

For example

\begin{axis}[
    azetinaplot,
    domain=-0.5:2.5, samples=100,
    xmin=-1, xmax=3,
    point legend/.style={ at={(rel axis cs:1.1,0.5)}},
    point 1/.style={anchor=south east}, point 2/.style={anchor=south east}
]
\derivative{\x^2}{$f(x)=x^2$}{1}{2}{$P_1=(1\,,\,1)$\\$P_2=(2\,,\,4)$}
\end{axis}

would yield

The azetinaplot style is defined here as

\pgfplotsset{
    azetinaplot/.style={
        width=7cm,
        height=7cm,
        axis lines=middle,
        xlabel=$x$,
        ylabel=$y$,
        enlarge y limits,
        clip=false
    }
}

Another example:

\begin{axis}[
    azetinaplot,
    domain=-20:370, samples=100,
    xmin=-20, xmax=370,
    point 1/.append style={anchor=south east},
    point 2/.append style={anchor=east}]
\derivative{sin(\x)}
    {$f(x)=\sin(x)$}
    {290}{340}
    {$P_1=(290\,,\,-0.94)$\\$P_2=(340\,,\,-0.34)$}
\end{axis}

would yield


Here's the complete code:

\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{matrix}

\begin{document}

\pgfplotsset{point legend/.style={},
    point 1/.style={anchor=south},
    point 2/.style={anchor=south}
}
\newcommand{\derivative}[5]{
\begin{scope}[declare function={f(\x)=#1;}]
    \addplot [thick, red, latex-latex] {f(x)} node [anchor=west] {#2};
    \addplot [black, mark=*] coordinates {(#3,{f(#3)}) (#4,{f(#4)})}
        node [pos=0,/pgfplots/point 1] {$P_1$}
        node [pos=1,/pgfplots/point 2] {$P_2$};
    \pgfplotsextra{
        \pgfmathsetmacro\first{f(#3)}
        \pgfmathsetmacro\second{(f(#4)}
        \pgfmathsetmacro\xdiff{#4-#3}
        \pgfmathsetmacro\ydiff{f(#4)-f(#3)}
        \draw (axis cs:#3,\first) -| (axis cs:#4,\second);
        \draw [|-|,yshift=-2ex] (axis cs:#3,\first) -- node [inner sep=1pt,fill=white] {\pgfmathprintnumber{\xdiff}} (axis cs:#4,\first);
        \draw [|-|,xshift=2ex] (axis cs:#4,\first) -- node [inner sep=1pt, fill=white] {\pgfmathprintnumber{\ydiff}} (axis cs:#4,\second);
        \matrix at (rel axis cs:1,1) [matrix of nodes,/pgfplots/point legend] {#5\\};
    }
    \end{scope}
}

\pgfplotsset{
    azetinaplot/.style={
        width=7cm,
        height=7cm,
        axis lines=middle,
        xlabel=$x$,
        ylabel=$y$,
        enlarge y limits,
        clip=false
    }
}

\begin{tikzpicture}
    \begin{axis}[
        azetinaplot,
        domain=-20:370, samples=100,
        xmin=-20, xmax=370,
        point 1/.append style={anchor=south east},
        point 2/.append style={anchor=east}]
    \derivative{sin(\x)}
        {$f(x)=\sin(x)$}
        {290}{340}
        {$P_1=(290\,,\,-0.94)$\\$P_2=(340\,,\,-0.34)$}
    \end{axis}
\end{tikzpicture}
\end{document}