12

I need to plot a function that presents some kind of removable singularity, but I cannot split the plot into two intervals, because I'm setting the domain programmatically and it can happen that the singularity falls out of the domain. I thought of using the ifthenelse function, but it's useless because both the expressions in the two branches are evaluated in any case. Look at the following code (it's just an example):

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture} [declare function={%
  y(\x)= \x!=0 ? sin(\x)/\x : 1;}]
\draw plot [domain=0:1] (\x,{y(\x)});
\end{tikzpicture}
\end{document}

I expected that, as x=0, the first branch of the expression was skipped and only the second one was evaluated, but it's not so and I get a division by zero error. As a solution, I thought of declaring an intermediate function to set properly the independent variable, as in the following working example:

\documentclass{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture} [declare function={%
  t(\x)= \x!=0 ? \x : 1;
  y(\x)= \x!=0 ? sin(\x)/t(\x) : 1;}]
\draw plot [domain=0:1] (\x,{y(\x)});
\end{tikzpicture}
\end{document}

but I'm looking for a more elegant and compact solution.

Luigi
  • 6,325

2 Answers2

11

Here is one possibility using math tikzlibrary:

\documentclass[border=7mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{math}
\tikzmath{
  function sinc(\x) {
    if  abs(\x) < .001 then {
      return 1;
    } else {
      return sin(\x r)/\x;
    };
  };
}

\begin{document}
\begin{tikzpicture}
  \draw[help lines] (-3.5,-1.5) grid (3.5,1.5);
  \draw[red, very thick] plot [domain=-pi:pi, samples=100] (\x,{sinc(5*\x)});
\end{tikzpicture}
\end{document}

enter image description here

Kpym
  • 23,002
6

Same as Kpym's answer but with no load of an additional library.

\documentclass{standalone}
\usepackage{tikz}

\makeatletter
\def\ifabsgreater #1#2{\ifpdfabsnum 
    \dimexpr#1pt>\dimexpr#2pt\relax
    \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi }
\makeatother

\begin{document}
\begin{tikzpicture} [declare function={%
          sinc(\x)= \ifabsgreater{\x}{0.001}{sin(\x r)/\x}{1};}]
 \draw[help lines] (-3.5,-1.5) grid (3.5,1.5);
 \draw[red, very thick] plot [domain=-pi:pi, samples=100] (\x,{sinc(5*\x)});
\end{tikzpicture}
\end{document}

sine cardinal

  • (+1) this is not for javascript programmers like me ;) – Kpym Jan 06 '15 at 15:33
  • @Kpym you mean there are no \expandafters in javascript? I am shocked ;) –  Jan 06 '15 at 15:34
  • I should not have called the thing \ifabsgreater but rather, for example \IfAbsGreater to signal it does not work as an \if conditional requiring a \fi. –  Jan 06 '15 at 16:48
  • I'm trying to modify your function to work with an equal sign but it fails in x=0 like in the question. Is there any way to let it work with the equal sign? – Luigi Jan 07 '15 at 18:20
  • I am not sure about what you mean. If \x is small the TikZ math parsing of sin(\x r)/\x will lead to dimension too large error, I imagine. Is this the kind of error you see? you should ask a new question if this too long to explain in a comment. –  Jan 07 '15 at 18:49
  • No. It isn't a dimension too large error but a division by zero error that is just what I wanted to avoid when I asked to prevent the function from being evaluated in x=0. If I use the @Kpym code substituting the < sign with the = one, it still works good. – Luigi Jan 07 '15 at 19:31
  • 1
    @jfbu, I'm sorry: I mistook the order of the two expressions. Your answer works good too. – Luigi Jan 07 '15 at 21:05