6

This question is about the answer of @TorbjørnT. in Math Error: The function 'f' already exists.

How can I add the third point, which has x coordinate as the mean of first two points and y coordinate is this x coordinated evaluated.

See picture

enter image description here

I tried (I indicated which lines I added)

\documentclass{article}
\usepackage{xparse} % for \NewDocumentCommand
\usepackage{pgfplots}
\usetikzlibrary{matrix}

\pgfplotsset{point legend/.style={},
    point 1/.style={anchor=south},
    point 2/.style={anchor=south}
}

\NewDocumentCommand{\derivative}{O{f} m m m m O{rel axis cs:1,1}}{
\tikzset{declare function={#1(\x)=#2;}}
    \addplot [thick, red, latex-latex] {#1(x)} node [anchor=west] {#3};
    \addplot [black, mark=*] coordinates {(#4,{#1(#4)}) (#5,{#1(#5)}) ((#5+#4)/2,#1((#5+#4)/2))} % I edited this line
        node [pos=0,/pgfplots/point 1] {$P_1$}
        node [pos=1,/pgfplots/point 2] {$P_2$}
        node [pos=0,/pgfplots/point 3] {$P_3$}; % I edited this line
    \pgfplotsextra{
        \pgfmathsetmacro\first{#1(#4)}
        \pgfmathsetmacro\second{#1(#5)} % removed first (
        \pgfmathsetmacro\xdiff{#5-#4}
        \pgfmathsetmacro\ydiff{#1(#5)-#1(#4)}
        \draw (axis cs:#4,\first) -| (axis cs:#5,\second);
        \draw [|-|,yshift=-2ex] (axis cs:#4,\first) -- node [inner sep=1pt,fill=white] {\pgfmathprintnumber{\xdiff}} (axis cs:#5,\first);
        \draw [|-|,xshift=2ex] (axis cs:#5,\first) -- node [inner sep=1pt, fill=white] {\pgfmathprintnumber{\ydiff}} (axis cs:#5,\second);
        \matrix at (#6) [matrix of math nodes,/pgfplots/point legend] {
         P_1=(#4\,,\,\pgfmathparse{#1(#4)}\pgfmathprintnumber{\pgfmathresult})\\
         P_2=(#5\,,\,\pgfmathparse{#1(#5)}\pgfmathprintnumber{\pgfmathresult})\\};
    }
}

\begin{document}



\pgfplotsset{
    azetinaplot/.style={
        width=10cm,
        height=8cm,
        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}
        [axis cs:150,-1] % position for the legend


    % above we used the default function name f
    % here we use the first optional argument to give the function the name g instead
    \derivative[g]{cos(\x)+2}
        {$f(x)=\cos(x)$}
        {200}{300}
        [axis cs:170,2.5] % position for the legend

    \end{axis}

\end{tikzpicture}
\end{document}

2 Answers2

3

I seems to work when you replace /2 by *0.5 -- for whatever reason.

% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{xparse}
\usepackage{pgfplots}
    \usetikzlibrary{matrix}
    \pgfplotsset{
        point legend/.style={},
        point 1/.style={anchor=south},
        point 2/.style={anchor=south},
        point 3/.style={anchor=south},                  % <-- added
        azetinaplot/.style={
            width=10cm,
            height=8cm,
            axis lines=middle,
            xlabel=$x$,
            ylabel=$y$,
            enlarge y limits,
            clip=false,
        },
    }
    \NewDocumentCommand{\derivative}{O{f} m m m m O{rel axis cs:1,1}}{
        \tikzset{declare function={#1(\x)=#2;}}
        %
        \addplot [thick, red, latex-latex] {#1(x)}
            node [anchor=west] {#3}
        ;
        \addplot [black, mark=*] coordinates {
            (#4,{#1(#4)})
            (#5,{#1(#5)})
        }
            node [pos=0,/pgfplots/point 1] {$P_1$}
            node [pos=1,/pgfplots/point 2] {$P_2$}
        ;
        % we need another `\addplot' for the third point to avoid drawing a line
        % also to point 2
        \addplot [black, mark=*, forget plot] coordinates {
            ({0.5*(#5+#4)},{#1(0.5*(#5+#4))})           % <-- repaced `/2' by `*0.5'
        }
            node [pos=0.5,/pgfplots/point 3] {$P_3$}    % <-- added
        ;
        \pgfplotsextra{
            \pgfmathsetmacro\first{#1(#4)}
            \pgfmathsetmacro\second{#1(#5)}
            \pgfmathsetmacro\xdiff{#5-#4}
            \pgfmathsetmacro\ydiff{#1(#5)-#1(#4)}
            %
            \draw (axis cs:#4,\first) -| (axis cs:#5,\second);
            \draw [|-|,yshift=-2ex] (axis cs:#4,\first)
                -- node [inner sep=1pt,fill=white] {\pgfmathprintnumber{\xdiff}}
                    (axis cs:#5,\first);
            \draw [|-|,xshift=+2ex] (axis cs:#5,\first)
                -- node [inner sep=1pt,fill=white] {\pgfmathprintnumber{\ydiff}}
                    (axis cs:#5,\second);
            %
            \matrix at (#6) [matrix of math nodes,/pgfplots/point legend] {
                P_1=(#4\,,\,\pgfmathparse{#1(#4)}\pgfmathprintnumber{\pgfmathresult})\\
                P_2=(#5\,,\,\pgfmathparse{#1(#5)}\pgfmathprintnumber{\pgfmathresult})\\
            };
        }
    }
\begin{document}
\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}
            [axis cs:150,-1] % position for the legend

        % above we used the default function name f
        % here we use the first optional argument to give the function the name g instead
        \derivative[g]{cos(\x)+2}
            {$f(x)=\cos(x)$}
            {200}{300}
            [axis cs:170,2.5] % position for the legend

    \end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

Stefan Pinnow
  • 29,535
  • thanks! Do you know how to remove the line between P3 and P2? – Faceb Faceb Jul 05 '18 at 18:16
  • With the current implementation this is not possible, because the point is added in the \addplot coordinates list. Thus, either no or all lines can be removed. Before we start iterating other requirements for your solution, please state all of them in your question. – Stefan Pinnow Jul 05 '18 at 18:45
  • that's all of the requirements. I would like the 3 points P1, P2, P3 but only P1 and P2 should be connected – Faceb Faceb Jul 05 '18 at 18:46
  • @FacebFaceb, please edit your question and add there all your requirements. in comments they are not well visible to others. and clarify, which line should be removed. so far i see only function curve, which is going through P3 and P2. do you like interrupt it? – Zarko Jul 06 '18 at 07:57
  • @FacebFaceb, did my answer answer your question? If yes, it would be nice if you could upvote it (by clicking on the arrows next to the score) and/or marking it as the accepted answer (by clicking on the checkmark ✓). – Stefan Pinnow Jul 08 '18 at 19:41
1

One way to go is to draw the line not as plot but as line. That way you can draw any fraction of it. For instance, here I draw only 50% of it.

\documentclass{article}
\usepackage{xparse} % for \NewDocumentCommand
\usepackage{pgfplots}
\usetikzlibrary{matrix}

\pgfplotsset{point legend/.style={},
    point 1/.style={anchor=south},
    point 2/.style={anchor=south}
}

\NewDocumentCommand{\derivative}{O{f} m m m m O{rel axis cs:1,1}}{
\tikzset{declare function={#1(\x)=#2;}}
    \addplot [thick, red, latex-latex] {#1(x)} node [anchor=west] {#3};
    \pgfplotsextra{
        \pgfmathsetmacro\first{#1(#4)}
        \pgfmathsetmacro\second{#1(#5)} % removed first (
        \pgfmathsetmacro\xdiff{#5-#4}
        \pgfmathsetmacro\ydiff{#1(#5)-#1(#4)}
        \pgfmathsetmacro\xmid{(#4+#5)/2}
        \path (axis cs:#4,{#1(#4)}) -- (axis cs:#5,{#1(#5)})
        node[pos=0,label=above:$P_1$]{\pgfuseplotmark{*}}
        coordinate[pos=0.5] (mid)
        node[pos=1,label=left:$P_2$]{{\pgfuseplotmark{*}}};
        \draw (axis cs:#4,{#1(#4)}) -- (mid);
        \node[label=above:{$P_3$}]at (axis cs:\xmid,{#1(\xmid)}) {\pgfuseplotmark{*}};
        \draw (axis cs:#4,\first) -| (axis cs:#5,\second);
        \draw [|-|,yshift=-2ex] (axis cs:#4,\first) -- node [inner sep=1pt,fill=white] {\pgfmathprintnumber{\xdiff}} (axis cs:#5,\first);
        \draw [|-|,xshift=2ex] (axis cs:#5,\first) -- node [inner sep=1pt, fill=white] {\pgfmathprintnumber{\ydiff}} (axis cs:#5,\second);
        \matrix at (#6) [matrix of math nodes,/pgfplots/point legend] {
         P_1=(#4\,,\,\pgfmathparse{#1(#4)}\pgfmathprintnumber{\pgfmathresult})\\
         P_2=(#5\,,\,\pgfmathparse{#1(#5)}\pgfmathprintnumber{\pgfmathresult})\\};
    }
}
 % node[pos=0.5,label=above left:$P_3$]{\pgfuseplotmark{*}}
\begin{document}



\pgfplotsset{
    azetinaplot/.style={
        width=10cm,
        height=8cm,
        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}
        [axis cs:150,-1] % position for the legend


    % above we used the default function name f
    % here we use the first optional argument to give the function the name g instead
    \derivative[g]{cos(\x)+2}
        {$f(x)=\cos(x)$}
        {200}{300}
        [axis cs:170,2.5] % position for the legend

    \end{axis}

\end{tikzpicture}
\end{document}

enter image description here