Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

How to define and plot a piecewise defined function in tikz or tkz-fct? For example consider the function

f(x) = 1 for x < 0, x for 0 <= x < 1, cos(x) for x >= 1

Edit:

After Torbjørn T.'s comment I tried the following. I should mention that I included three different versions of plotting the function because I want that all three versions should work.

\documentclass{article}
\usepackage{amsmath}
\usepackage{pgfplots}
\usepackage{tkz-fct}

\pgfmathdeclarefunction{p}{3}{%
  \pgfmathparse{(and(#1>#2, #1<#3))}%
}

\pgfmathdeclarefunction{f}{1}{%
  \pgfmathparse{p(#1,-100,0)*1 + p(#1,0,1)*#1 + p(#1,1,100)*cos(#1r)}
}

\begin{document}

\begin{tikzpicture}
   \tkzInit[xmin=-1,xmax=5,ymax=4] %
   \tkzGrid %
   \tkzAxeXY %
   \tkzFct{f(x)} %
   \draw plot function{f(x)};%
      \begin{scope}[xshift=4cm]
      \begin{axis}
         \addplot[domain=-2:4,samples=100]{f(x)};
      \end{axis}
   \end{scope}
\end{tikzpicture}


\end{document}

Which gives the following output:

output

share|improve this question
4  
Does this help? tex.stackexchange.com/questions/19510/… –  Torbjørn T. Nov 3 '11 at 18:50
    
Thanks, I tried something with it, see edit above, but it doesn't work... –  student Nov 3 '11 at 19:38
1  
I can't test here (windows), but I presume you would want your r inside of the cos. Also this does not cover the cases where x=0 and x=1, although that should not cause too much problems. –  Roelof Spijker Nov 3 '11 at 20:28
    
@wh1t3: Thanks, I put the r inside of the cos now –  student Nov 3 '11 at 21:40

4 Answers 4

There are a few problems with the code:

  1. PGF uses degrees for trig functions
  2. Seems that the r at the end of the function f was intended to convert from radians to degree, but I changed it so that it is more obvious.
  3. Need to determine what happens at the end points of the piecewise domain, so note the slight tweaks for that.
  4. Not sure what the tkz portion of the code has to do with the problem of defining a piecewise function, so have commented that out.
  5. Be careful using single letter function names as documented in: Why do 2 identical function definitions with different names produce two different plots?

So, with slight modifications to your code I can produce the following. Note that there still is a problem around x=1 as pgf does not know what to do.

enter image description here

\documentclass[border=2pt]{standalone}
\usepackage{amsmath}
\usepackage{pgfplots}
\usepackage{tkz-fct}

\pgfmathdeclarefunction{p}{3}{%
  \pgfmathparse{(and(#1>#2, #1<#3))}%
}

\pgfmathdeclarefunction{f}{1}{%
  \pgfmathparse{p(#1,-100,-0.001)*1 + p(#1,0,1)*#1 + p(#1,1.01,100)*cos(deg(#1))}%
}

\begin{document}
\begin{tikzpicture}
%   \tkzInit[xmin=-1,xmax=5,ymax=4] %
%   \tkzGrid %
%   \tkzAxeXY %
%   \tkzFct{f(x)} %
%   \draw plot function{f(x)};%
      \begin{scope}[xshift=6cm]
      \begin{axis}
         \addplot[ultra thick, blue,domain=-2:4,samples=100]{f(x)};
      \end{axis}
   \end{scope}
\end{tikzpicture}
\end{document}

What I would recommend is that you draw the three separate portions individually and avoid the problem areas via a fixed value of \Tolerance:

enter image description here

\documentclass[border=2pt]{standalone}
\usepackage{amsmath}
\usepackage{pgfplots}
\usepackage{tkz-fct}

\pgfmathdeclarefunction{p}{3}{%
  \pgfmathparse{(and(#1>#2, #1<#3))}%
}

\newcommand{\Tolerance}{0.0001}%
\pgfmathdeclarefunction{f}{1}{%
  \pgfmathparse{%
    p(#1,-\maxdimen,-\Tolerance)*1.0 +%
    p(#1,0,1-\Tolerance)*#1 +%
    p(#1,1,\maxdimen)*cos(deg(#1))}%
}

\begin{document}
\begin{tikzpicture}
%   \tkzInit[xmin=-1,xmax=5,ymax=4] %
%   \tkzGrid %
%   \tkzAxeXY %
%   \tkzFct{f(x)} %
%   \draw plot function{f(x)};%
      \begin{scope}[xshift=6cm]
      \begin{axis}
         \addplot[ultra thick, blue,domain=-2:-\Tolerance,samples=100]{f(x)};
         \addplot[ultra thick, green,domain=\Tolerance:1-\Tolerance,samples=100]{f(x)};
         \addplot[ultra thick, red,domain=1+\Tolerance:4,samples=100]{f(x)};
      \end{axis}
   \end{scope}
\end{tikzpicture}
\end{document}

To clarify, the \addplot calls above are really just:

\addplot[ultra thick, blue, domain=-2.0000:-0.0001, samples=100]{f(x)};
\addplot[ultra thick, green,domain= 0.0001: 0.9999, samples=100]{f(x)};
\addplot[ultra thick, red,  domain= 1.0001: 4.0000, samples=100]{f(x)};
share|improve this answer
    
The tkz portion is because I want also be able to plot those functions using tkz-fct. –  student Nov 3 '11 at 21:33
    
@Peter Grill Thanks, your second picture looks fine, however the source code looks pretty complicated. I want a solution where I have a simple syntax to plot much more complicated piecewise defined functions, too. –  student Nov 3 '11 at 21:45
    
I too am looking for that since I posted the question you referred to in your posting. But I think the second one looks more complicated as I defined \Tolerance so it was easy to adjust. –  Peter Grill Nov 3 '11 at 21:48

I slightly modified @Herbert's code to make the graph of f (visually) "a graph of a function". It still has few quirks.

\documentclass{article}
\usepackage{pstricks-add}
\pagestyle{empty}
\begin{document}    
\begin{pspicture}(-1,-1)(7,1)
\psplot[algebraic,linecolor=red,plotpoints=1000,
        linewidth=1pt]{-1}{7}{IfTE(x<0,1,IfTE(x<1,x,cos(x)))}
\psline[linecolor=white,linewidth=1pt](0,1)(0,0)
\psline[linecolor=white,linewidth=2pt](1,.96)(1,0.54)
\psaxes[trigLabels,xunit=\pstRadUnit,trigLabelBase=3]{->}(0,0)(-1,-1)(7,1.2)
\end{pspicture}
\end{document}

enter image description here

share|improve this answer

I would use the ifthenelse structure (available in tikz and in gnuplot).

\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\begin{document}

% plain tikz + ifthenelse:
\begin{tikzpicture}[scale=3]
  \draw[blue,thick] plot[samples=200,domain=-2:4] (\x,{ifthenelse(\x <
    0,1,ifthenelse(and(\x >= 0,\x < 1),\x, cos(deg(\x))))});  
  \draw[red,thick,semitransparent] plot[samples=200,domain=-2:4]
    (\x,{cos(deg(\x))});   
\end{tikzpicture}

% pgfplots + gnuplot:
\begin{tikzpicture}
  \begin{axis}
    \addplot+[samples=150,domain=-2:4] function {x < 0 ? 1 : ((x >=0)
      && (x<1)) ? x : cos(x)}; 
    \addplot+[samples=150,domain=-2:4,semitransparent] function {cos(x)}; 
  \end{axis}
\end{tikzpicture}

% plain tikz with '?' operator: 
\begin{tikzpicture}[scale=3]
  \draw plot[samples=200,domain=-2:4] (\x,{\x < 0 ? 1 : (((\x >=0)
      && (\x<1)) ? \x : cos(deg(\x)))});
\end{tikzpicture}

% pgfplots without gnuplot: (requires developer version of pgf or pgfplots):
\begin{tikzpicture}
  \begin{axis}
    \addplot[blue,samples=150,domain=-2:4] {x < 0 ? 1 : (((x >=0)
      && (x<1)) ? x : cos(deg(x)))}; 
  \end{axis}
\end{tikzpicture}
\end{document}

An example

share|improve this answer
    
This does not appear to be using the cos function for x>1. –  Peter Grill Nov 3 '11 at 20:39
    
@PeterGrill It does (see my updated answer), but I did not believe it either! –  cjorssen Nov 3 '11 at 20:53
    
The OP used domain=-2:4 so probably best to stick to that domain so that the results are easy to compare. –  Peter Grill Nov 3 '11 at 21:20
    
@cjorssen I like your answer. I took the freedom to add variants using the ? operator as well. And by the way: I found that \usetikzlibrary{fpu} (which is used by pgfplots), did not properly support it. I have just comitted support for ==, !=, <=, >=, ? to pgf CVS. The last example will only compile with this commit. –  Christian Feuersänger Nov 3 '11 at 21:24
    
@ChristianFeuersänger Thanks! I was investigating to understand why it didn't work for me. I changed the domain to stick to the OP one. –  cjorssen Nov 3 '11 at 21:37

Run with xelatex

%f(x) = 1 for x < 0, x for 0 <= x < 1, cos(x) for x >= 1

\documentclass{article}
\usepackage{pstricks-add}
\pagestyle{empty}
\begin{document}    
\begin{pspicture}(-1,-1)(7,1)
\psaxes[trigLabels,xunit=\pstRadUnit,trigLabelBase=3]{->}(0,0)(-1,-1)(7,1.2)
\psplot[algebraic,linecolor=red,plotpoints=1000,
        linewidth=1pt]{-1}{7}{IfTE(x<0,1,IfTE(x<1,x,cos(x)))}
\end{pspicture}
\end{document}

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.