Consistently specify a Function and use it for computation and plotting

4,397

If you define your function using \def\<function macro>(#1){\pgfmathparse{...#1...}, you can use the function in all the applications you mentioned by saying \<function macro>(x) or \<function macro>(x-1), or \<function macro>(2.4). This will work both when using Gnuplot and when using straight PGFplots:

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}

\def\FunctionF(#1){(#1)^3}%

\newcommand*{\SpecialXValue}{1.5}%

\begin{document}
\begin{tikzpicture}
\begin{axis}[
    domain=-3:3, samples=50,
    enlargelimits=false,
    ymin=-5, ymax=5,
    every axis plot post/.style= ultra thick]
    \addplot [red] gnuplot {\FunctionF(x)};%
    \addplot [blue] gnuplot {\FunctionF(x+1)};%
    \addplot [cyan] {(x<1)*(3-3*x)+!(x<1)*-\FunctionF(x-1.5))};
    \pgfmathsetmacro{\specialY}{\FunctionF(-1.5)}
    \fill (axis cs:-1.5,\specialY) circle [radius=2pt] node [right] {(2,\specialY)};
\end{axis}


\end{tikzpicture}
\end{document}

Old Answer:

You can redefine the x function to return a constant value (in your case \SpecialXValue) before calculating the y value. The easiest way to do that is to issue

\tikzset{declare function={x=\SpecialXValue;}}

just before you calculate the y value.

You can still add new functions after this, the definition of x as a fixed value doesn't persist.

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}

\newcommand*{\XAxisMin}{-1.0}
\newcommand*{\XAxisMax}{3.0}
\newcommand*{\YAxisMin}{-2.0}
\newcommand*{\YAxisMax}{10}

\newcommand*{\DomainMinF}{\XAxisMin}
\newcommand*{\DomainMaxF}{2.2}

\pgfkeys{/pgfplots/Axis Style/.style={
    xmin=\XAxisMin, xmax=\XAxisMax,
    ymin=\YAxisMin, ymax=\YAxisMax, 
    domain=\DomainMinF:\DomainMaxF,
    width=6.5cm
}}

% Gnuplot options here  have no effect if not using GnuPlot
\pgfkeys{/pgfplots/Plot Style/.style={
    translate gnuplot=true,% can use ‘^’ instead of ‘**’
    id=foo,
    mark=none,%
    domain=\DomainMinF:\DomainMaxF,%
    samples=50,%
    ultra thick,
}}

\newcommand*{\LabelPoint}[2]{\fill (axis cs:#1,#2) circle [radius=3pt] node [right] {\footnotesize$(#1,#2)$};}%


\newcommand*{\FunctionFGnuplot}{(x)^3}%

\newcommand*{\SpecialXValue}{1.1}%

\begin{document}
\begin{tikzpicture}
\begin{axis}[Axis Style]
    \addplot [Plot Style, red] gnuplot {\FunctionFGnuplot};%

    \tikzset{declare function={x=\SpecialXValue;}}
    \pgfmathsetmacro{\YatSpecialX}{\FunctionFGnuplot}%
    \LabelPoint{\SpecialXValue}{\YatSpecialX}
\end{axis}


\end{tikzpicture}
\end{document}
Share:
4,397

Related videos on Youtube

Peter Grill
Author by

Peter Grill

Updated on June 12, 2020

Comments

  • Peter Grill
    Peter Grill over 2 years

    I would like to be able to specify a mathematical function and be able to use that for multiple purposes including:

    1. Computation of values (see bullet points below)
    2. Graphing using pgfplot
    3. Graphing using pgfplots/gnuplot

    This could be considered a followup to: Consistently specify function to be graphed with or without gnuplot which addresses points 2 and 3 where it was pointed out that with the definition of a function as

    \newcommand*{\FunctionF}{(x)^3}%
    

    one could use it to plot with just PGFplots, or in conjunction with gnuplot:

    \addplot {\FunctionF};
    \addplot gnuplot {\FunctionF};
    

    But, I desire a way to also be able to use the same definition to do computations such as where

    • I want to define a piecewise function as in Defining a Piecewise Function for PGFplots,

    • be able to use it to compute values of individual points as in this example where I label a specific point given the x value

    • be able to use it as any other built in math function and define a translation as in the green curve below

    enter image description here

    So to produce the blue line graph, I have used the \pgfmathdeclarefunction definition which solves problems 1 and 2, and the above referenced question uses the \newcommand*{\FunctionF}{(x)^3} definition to solve problems 2 and 3.

    Question: Is there someway of solving problems 1, 2 and 3 all with one definition of the function?

    \documentclass[border=5pt]{standalone}
    \usepackage{pgfplots}
    
    \newcommand*{\XAxisMin}{-1.0}
    \newcommand*{\XAxisMax}{3.0}
    \newcommand*{\YAxisMin}{-2.0}
    \newcommand*{\YAxisMax}{10}
    
    \newcommand*{\DomainMinF}{\XAxisMin}
    \newcommand*{\DomainMaxF}{2.2}
    
    \pgfkeys{/pgfplots/Axis Style/.style={
        xmin=\XAxisMin, xmax=\XAxisMax,
        ymin=\YAxisMin, ymax=\YAxisMax, 
        domain=\DomainMinF:\DomainMaxF,
        width=6.5cm
    }}
    
    % Gnuplot options here  have no effect if not using GnuPlot
    \pgfkeys{/pgfplots/Plot Style/.style={
        translate gnuplot=true,% can use ‘^’ instead of ‘**’
        id=foo,
        mark=none,
        domain=\DomainMinF:\DomainMaxF,
        samples=50,
        ultra thick,
    }}
    
    \newcommand*{\AddLabel}[1]{\node [align = center] at (axis cs: 0.25,7.1) {#1};}%
    \newcommand*{\LabelPoint}[2]{\addplot [mark=*] coordinates {(#1,#2)} node [right] {\footnotesize$(#1,#2)$};}%
    %-----------------------------
    
    % I would like to only have to specify the function here once
    \pgfmathdeclarefunction{FunctionF}{1}{\pgfmathparse{(#1)^(3)}}%
    \newcommand*{\FunctionFGnuplot}{(x)^3}%
    
    % Define translation of F
    \pgfmathdeclarefunction{FunctionG}{1}{\pgfmathparse{FunctionF(#1+1.0)}}%
    
    
    \newcommand*{\SpecialXValue}{1.1}%
    
    \begin{document}
    \begin{tikzpicture}
    \begin{axis}[Axis Style]
        \addplot [Plot Style, blue] ({x},{FunctionF(x)});
        \addplot [Plot Style, green]({x},{FunctionG(x)});
    
        \AddLabel{1. without \\ Gnuplot}
        \node at (axis cs: 1.8,3.0) [blue] {$f(x)$};
        \node at (axis cs: -0.2,3.0) [green] {$f(x+1)$};
    
        \pgfmathsetmacro{\YatSpecialX}{FunctionF(\SpecialXValue)}
        \LabelPoint{\SpecialXValue}{\YatSpecialX}
    \end{axis}
    \end{tikzpicture}
    %
    \begin{tikzpicture}
    \begin{axis}[Axis Style]
        \addplot [Plot Style, red] gnuplot {\FunctionFGnuplot};
        \AddLabel{2. with Gnuplot \\
                \footnotesize(but resorted to using \\
                \footnotesize pgfmathdeclarefunction \\
                \footnotesize to compute point)}
    
        % How do I do something like this with \FunctionFGnuplot
        \pgfmathsetmacro{\YatSpecialX}{FunctionF(\SpecialXValue)}
        \LabelPoint{\SpecialXValue}{\YatSpecialX}
    \end{axis}
    \end{tikzpicture}
    \end{document}
    
    • Jake
      Jake almost 11 years
      Instead of using \addplot [mark=*] coordinates {(#1,#2)} node ... in your \LabelPoint, I would suggest using \fill (axis cs:#1,#2) circle [radius=2pt] node .... Starting a whole new plot just for drawing one point will introduce unnecessary overhead, plus it can get in the way if you use legends, because the point will get its own entry unless you use forget plot.
    • Christian Feuersänger
      Christian Feuersänger almost 11 years
      Peter, I suppose an approach like \addplot ... node[pos=0.6] {} is not precisely what you have in mind, right? You want to specify the coordinate here, don't you? Because if a relative position is sufficient, I have an almost stable prototype for it, compare other related questions. The approach includes output of the coordinates of the designated point.
    • Peter Grill
      Peter Grill almost 11 years
      @Jake: Good point about using \fill. I created these macros when I was first starting out and need to go an revisit all of them someday.
    • Peter Grill
      Peter Grill almost 11 years
      @ChristianFeuersänger: The relative position labeling will be extremely useful, but in this case I need to compute values.
    • Vivi
      Vivi over 9 years
      Don't you hate it when you spend 30 minutes writing up a question only to realise there is another one which gives you exactly what you need?
    • Peter Grill
      Peter Grill over 9 years
      @Vivi: :-) Yep!! Have done that numerous times!! Only after you actually find the problem, compose the MWE, get ready to post the question, do you locate the relevant question. Here is an example where after composing it I had to alter it slightly: Why is \parskip zero inside a minipage?.
  • Vivi
    Vivi over 9 years
    Jake, instead of using the \SpecialY construct, I find it easier to just include in the node {(2,{\FunctionF(-1.5)})}. As long as you enclose the \FunctionF() in curly brackets it should compile fine. Any other reason why you use the \SpecialY?
  • Jake
    Jake over 9 years
    @Vivi: Yup: Copying from the OP =). I agree with you, \FunctionF(-1.5) seems more readable to me as well.