Consistently specify a Function and use it for computation and plotting
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}
Related videos on Youtube
Peter Grill
Updated on June 12, 2020Comments
-
Peter Grill almost 3 years
I would like to be able to specify a mathematical function and be able to use that for multiple purposes including:
- Computation of values (see bullet points below)
- Graphing using pgfplot
- 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 withgnuplot
:\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
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 over 11 yearsInstead 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 useforget plot
. -
Christian Feuersänger over 11 yearsPeter, 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 over 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 over 11 years@ChristianFeuersänger: The relative position labeling will be extremely useful, but in this case I need to compute values.
-
Vivi over 10 yearsDon'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 over 10 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 over 10 yearsJake, 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 over 10 years@Vivi: Yup: Copying from the OP
=)
. I agree with you,\FunctionF(-1.5)
seems more readable to me as well.