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.

I'm trying to draw (in TikZ) a convex function f constructed as the minimum of the linear functions f1, f2, f3 and f4. To do that, my inclination is to use the intersections of said lines to find the minimum, but the line intersection doesn't seem to allow me to do that. Concretely, I have the following code:

\documentclass{article}
\nonstopmode

\usepackage{tikz}

\usetikzlibrary{calc,intersections}

\begin{document}
\begin{tikzpicture}[scale=.5]

    \draw[-stealth] (0,0) -- (10,0) node [below right] {};
    \draw[-stealth] (0,0) -- (0,10) node [left=2] {};

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    \foreach \a/\b [count=\i] in {60/1.7, 45/2.4, 30/3.7, 18/5.5} {
        \begin{scope}
            \clip (0,0) rectangle (10,10);
            \draw (0,\b) -- +(\a:20);
        \end{scope}
        \node [left] at (0,\b) {$f_\i$};
    }

    % the following doesn't work because the "intersection of" doesn't like
    % the coordinates, or so it seems
    %\def\lasta{90}\def\lastb{0}
    %\draw[red, thick] (0,0) 
    %    \foreach \a/\b [remember=\a as \lasta, remember=\b as \lastb]
    %        in {60/1.7, 45/2.4, 30/4, 23/5} -- 
    %        (intersection of (0,\lastb)--+(\lasta:20) and (0,\b)--+(\a,20));
\end{tikzpicture}
\end{document}

result

I'd like to draw, with a fat red line, the function f that is the point-wise minimum of all of those, in a generic way. Any comments are welcome, but my question boils down to this:

How can I take the intersections of said lines, without manually unfolding the loops?

share|improve this question
    
Welcome to TeX.sx! Note that MathJax is disabled here, because we normally want to display the TeX code instead of the result. In this simple case Markdown and HTML also do the trick. I included the image for you. You should soon have enough reputation to do that by yourself. –  Martin Scharrer Apr 3 '12 at 13:43
    
Note that in mathematics, that one is called a concave function. It's confusing, but that's what it is. –  celtschk Apr 3 '12 at 20:01
add comment

3 Answers

up vote 6 down vote accepted

With only TikZ but with functions. Remark : I use samples=2 to draw the lines because two points are enough but for m we need enough points to find the correct min values. I use a part of the Jake's answer.

\documentclass{article}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[declare function={
    f(\t)=tan(60)*\t+1.7;
    g(\t)=tan(45)*\t+2.4;
    h(\t)=tan(30)*\t+3.7;
    i(\t)=tan(18)*\t+5.5;
    m(\t)=min(f(\t) ,g(\t) ,h(\t),i(\t));}] 

 \draw[very thin,color=gray] (-0.1,-0.1) grid (10.1,10);
 \draw[->] (-0.2,0) -- (10.2,0) node[right] {$x$};
 \draw[->] (0,-0.2) -- (0,10.2) node[above] {$y$};  

 \clip (-1,-1) rectangle (10,10);     
\foreach \func in {f,g,h,i}
\draw [blue, thin] plot [domain=0:10, samples=2] (\x,{\func(\x)});
\draw [red, thick] plot [domain=0:10, samples=100] (\x,{m(\x)}); 
\end{tikzpicture}

\end{document} 

enter image description here

share|improve this answer
    
Ah, good idea drawing the straight lines with only two samples! –  Jake Apr 3 '12 at 15:25
    
thanks ! yes it's enough and a lot of users keep the value by default. –  Alain Matthes Apr 3 '12 at 15:30
    
Another terrific solution. Didn't know we could use functions this way, as a functional programming, that's a feature I'm gonna (ab)use a lot. –  stygianguest Apr 3 '12 at 18:04
add comment

Not a direct answer to the question, but rather a suggestion of a different approach: If you use PGFplots and treat your lines as proper functions, you can plot the convex function simply using \addplot {min(f,g,h,i)};:

\documentclass{article}

\usepackage{pgfplots}


\begin{document}

\begin{tikzpicture}[/pgf/declare function={
    f=tan(60)*x+1.7;
    g=tan(45)*x+2.4;
    h=tan(30)*x+3.7;
    i=tan(18)*x+5.5;
    }
]
\begin{axis}[
    axis lines=left,    % no box
    domain=-1:20, samples=100, % evaluate functions from 0:20 with 100 samples
    xmin=0, ymin=0, ymax=10, % set y limits
    no markers, % don't mark each point
    unit vector ratio*=1 1 1, % length of x unit = length of y unit
    xtick=\empty, ytick=\empty, % no tick marks
    cycle list={} % all plots the same colour unless specified otherwise
]

\addplot [line width=3pt, red!50!white] {min(f,g,h,i)};
\foreach \function in {f,...,i} {
    \addplot [samples=2] {\function}; % straight lines only need two samples. Taken from Altermundus' answer.
}
\end{axis}
\end{tikzpicture}
\end{document}
share|improve this answer
    
I have to admit this is a very nice solution. The reason I stopped using pgfplots was because it interacted badly with some tikz features and animations in presentations and I just stuck with it. I still have some latent irrational fear of it, but your solution convinced me! –  stygianguest Apr 3 '12 at 17:56
add comment

I like Jake's solution. However, if for some weird reason you don't want to use pgfplots you can use the name intersections approach. That would look like this:

\documentclass{article}
\nonstopmode
\usepackage{tikz}
\usetikzlibrary{calc,intersections}
\begin{document}
  \begin{tikzpicture}[scale=.5]

    \draw[-stealth] (0,0) -- (10,0) node [below right] {};
    \draw[-stealth] (0,0) -- (0,10) node [left=2] {};
    \foreach \a/\b [count=\i] in {60/1.7, 45/2.4, 30/3.7, 18/5.5} {
        \begin{scope}
            \clip (0,0) rectangle (10,10);
            \draw[name path global=\i path] (0,\b) -- +(\a:20);
        \end{scope}
        \node [left] at (0,\b) {$f_\i$};
    }
    \coordinate (last) at (0,0);
    \foreach \i [count=\j] in {2,...,4}{
      \path[draw,red,thick, name intersections={of=\j path and \i path}] (last) -- (intersection-1) coordinate (last);
    }
    \path (0,5.5) +(18:20) coordinate (final);
    \clip (0,0) rectangle (10,10);
    \draw[red,thick] (last) -- (final);
  \end{tikzpicture}
\end{document}

and the result:

convex function

share|improve this answer
    
Very nice! The starting point should be \coordinate (last) at (0,1.7); (instead of (0,0)), though. –  Jake Apr 3 '12 at 15:38
    
I had tried to do this, but couldn't get it to work. I wrongly assumed it wasn't possible to name paths with a variable, i.e., \draw[name path global=\i path]... Learning a lot here! –  stygianguest Apr 3 '12 at 18:03
1  
Wait a second, this is technically the only ``exact'' answer right? The others sample to obtain the minimum, but since it's completely invisible. I'd give extra points for that :) –  stygianguest Apr 3 '12 at 18:08
    
@Jake: I copied the starting point from his code :). For it to be the minimum it should indeed be (0,1.7). @stygianguest I like Altermundus's answer better, you should see mine more like an example of how to use the name path and name intersection constructs. –  Roelof Spijker Apr 4 '12 at 7:35
add comment

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.