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 wish to fill the area enclosed by four functions, as indicated by the hatching in red in the figure below:

enter image description here

So far I've been able to fill the area between each pair of functions, as shown below:

enter image description here

The first was produced as follows:

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

\pgfmathdeclarefunction{fun1}{0}{%
  \pgfmathparse{ tan(x)/( cos(x)*( 1 + 3.3*((tan(x))^2) ) ) }}
\pgfmathdeclarefunction{fun2}{0}{%
  \pgfmathparse{ 1.1*tan(x)*(1/cos(x)) }}
\pgfmathdeclarefunction{fun3}{0}{%
  \pgfmathparse{ 0.145*( ( 1 + 3.3*(tan(x))^2 ) / sin(x) ) }}
\pgfmathdeclarefunction{fun4}{0}{%
  \pgfmathparse{ 4 }}

\begin{tikzpicture}
%
\begin{semilogyaxis}[%
width=7cm,height=11cm,
scale only axis,
xmin=0, xmax=90,
xmajorgrids,
ymin=0.1, ymax=10,
ymajorgrids,yminorgrids]

% fun1 (start stacking)
\addplot[
domain=1:25.70,
draw=none,fill=none,mark=none,
stack plots=y]
{ fun1 };
%
% stack difference between fun2 and fun1 on top of fun1
\addplot[
domain=1:25.70,
draw=none,draw opacity=0.0,
fill=gray,fill opacity=0.25,
stack plots=y
]
{ max( fun2 - fun1 , 0 ) }
\closedcycle;

% fun1
\addplot[domain=1:89,solid,line width=0.8pt,draw=black,mark=none]{ fun1 };

% fun2 (branch 1)
\addplot[domain=1:25.78,solid,line width=0.8pt,draw=black,mark=none]{ fun2 };
% fun2 (branch 2)
\addplot[domain=25.78:89,dashed,draw=black,mark=none]{ fun2 };

% fun3 (branch 1)
\addplot[domain=1:89,dashed,draw=black,mark=none]{ fun3 };
% fun3 (branch 2)
\addplot[domain=25.78:70,solid,line width=0.8pt,draw=black,mark=none]{ fun3 };
% fun3 (branch 3)
\addplot[domain=70:89,dashed,draw=black,mark=none]{ fun3 };

% fun4 (branch 1)
\addplot[domain=1:70,dashed,draw=black,mark=none]{ fun4 };
% fun4 (branch 2)
\addplot[domain=70:89,solid,line width=0.8pt,draw=black,mark=none]{ fun4 };

\end{semilogyaxis}
\end{tikzpicture}
\end{document}

The 2nd and 3rd were obtained, respectively, using:

  • domain=25.78:70 and { max( fun3 - fun1 , 0 ) }
  • domain=70:89 and { max( fun4 - fun1 , 0 ) }

How can I display them on a single plot?

share|improve this question
    
If what you want is combining three plots into one tikzpicture, I don't see how the current title (Fill the area enclosed by multiple functions) is descriptive of the problem at all... –  Jubobs May 6 '13 at 9:23
    
@Jubobs feel free to edit the title, or otherwise suggest a more appropriate one. –  nnunes May 6 '13 at 9:38
    
@nnunnes Oops. Sorry; I had completely misunderstood your question. I'll scrap my answer. Your lastest edit helps a lot in clarifying the question, I think. –  Jubobs May 6 '13 at 9:40
    
@Jubobs Thanks for that! –  nnunes May 6 '13 at 9:42
add comment

2 Answers

up vote 8 down vote accepted

You can define a new piecewise function fun5(x) combining fun2, fun3 and fun4 and fill the area between fun1 and fun5:

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.8}
\begin{document}

\pgfmathdeclarefunction{fun1}{1}{%
  \pgfmathparse{tan(#1)/(cos(#1)*(1+3.3*((tan(#1))^2)))}}
\pgfmathdeclarefunction{fun2}{1}{%
  \pgfmathparse{1.1*tan(#1)*(1/cos(#1))}}
\pgfmathdeclarefunction{fun3}{1}{%
  \pgfmathparse{0.145*((1+3.3*(tan(#1))^2)/sin(#1))}}
\pgfmathdeclarefunction{fun4}{1}{%
  \pgfmathparse{4}}
\pgfmathdeclarefunction{fun5}{1}{%
  \pgfmathparse{%
    (#1>=1 && #1<=25.78)*fun2(#1) +%
    (#1>25.78 && #1<=70)*fun3(#1) +%
    (#1>70 && #1<89)*fun4(#1)}}

\begin{tikzpicture}
%
\begin{semilogyaxis}[%
width=7cm,height=11cm,
scale only axis,
xmin=0, xmax=90,
xmajorgrids,
ymin=0.1, ymax=10,
ymajorgrids,yminorgrids]
% area
\addplot [domain=1:89,draw=none,stack plots=y]
         {fun1(x)};
%         
\addplot [domain=1:89,draw=none,fill=gray,fill opacity=0.25,stack plots=y]
         {max(fun5(x) - fun1(x),0)}
\closedcycle;
%
% fun1
\addplot [domain=1:89,line width=0.8pt] {fun1(x)};
% fun2 (branch 1)
\addplot[domain=1:25.78,solid,line width=0.8pt]{fun2(x)};
% fun2 (branch 2)
\addplot[domain=25.78:89,dashed]{fun2(x)};
%
% fun3 (branch 1)
\addplot[domain=1:89,dashed]{fun3(x)};
% fun3 (branch 2)
\addplot[domain=25.78:70,line width=0.8pt]{fun3(x)};
% fun3 (branch 3)
\addplot[domain=70:89,dashed]{fun3(x)};
%
% fun4 (branch 1)
\addplot[domain=1:70,dashed]{fun4(x)};
% fun4 (branch 2)
\addplot[domain=70:89,line width=0.8pt]{fun4(x)};
\end{semilogyaxis}
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
add comment

Version 1.10 of pgfplots has been released just recently, and it comes with a new solution for the problem to fill the area between plots.

Note that the old solution is still possible and still valid; this here is merely an update which might simplify the task. In order to keep the knowledge base of this site up-to-date, I present a solution based on the new fillbetween library here:

enter image description here

\documentclass{standalone}
\usepackage{pgfplots}

\pgfplotsset{compat=1.10}
\usepgfplotslibrary{fillbetween}

\begin{document}

\pgfmathdeclarefunction{fun1}{0}{%
  \pgfmathparse{ tan(x)/( cos(x)*( 1 + 3.3*((tan(x))^2) ) ) }}
\pgfmathdeclarefunction{fun2}{0}{%
  \pgfmathparse{ 1.1*tan(x)*(1/cos(x)) }}
\pgfmathdeclarefunction{fun3}{0}{%
  \pgfmathparse{ 0.145*( ( 1 + 3.3*(tan(x))^2 ) / sin(x) ) }}
\pgfmathdeclarefunction{fun4}{0}{%
  \pgfmathparse{ 4 }}

\begin{tikzpicture}
%
\begin{semilogyaxis}[%
width=7cm,height=11cm,
scale only axis,
xmin=0, xmax=90,
xmajorgrids,
ymin=0.1, ymax=10,
ymajorgrids,yminorgrids]


% fun1
\addplot[name path=fun1,domain=1:89,red]{ fun1 };

% fun2 
\addplot[name path=fun2,domain=1:78.89,blue]{ fun2 };

% fun3 
\addplot[name path=fun3,domain=1:89,brown,]{ fun3 };

% fun4 
\addplot[name path=fun4,domain=1:89,orange]{ fun4 };

\path[name path=intermediate,
     %draw, line width=2pt,
    intersection segments={of=fun2 and fun3,
        sequence=A0 -- B1,
    },
];
\path[name path=segments,
    %draw, line width=2pt,
    intersection segments={of=intermediate and fun4,
        sequence=A0 -- B1,
    },
];

\addplot[gray,fill opacity=0.25] fill between[of=segments and fun1];
\end{semilogyaxis}
\end{tikzpicture}

\end{document}

This solution just has the four functions without any modifications. However, it assigns a label to each of them. Then, we have to \path instructions which compute intersection segments: the first \path instruction generates an intermediate path which will be discarded. Note that \path without draw or fill has no visible output (and generates only scopes in the resulting pdf, no path instructions). The first intermediate path consists of the intersection segments of fun2 and fun3, namely the segments A0 which means "first (0th) segment of the first argument (fun2)". Graphically, this is the lower left edge of the filled region (blue and brown). The first argument is always called A in this context, segment indices start at 0. This segment is connected with B1 which means the second (1st) segment of the second argument in of=fun2 and fun3 (i.e. the second segment of fun3).

The second \path instruction computes intersection segments of intermediate and fun4. Keep in mind that fun4 is the top path (the orange one). Here, we take A0 (the first intersection segment of intermediate) and connect it with B1 (the second = 1st segment of fun4).

Both of these \path instructions result in no visible output (unless you insert the uncomment draw keys). They only store the results under a name.

Finally, the last \addplot fill between statement fills the area between our computed segments and fun1. To this end, it uses the fill options gray,fill opacity=0.25.

share|improve this answer
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.