pgfplots – How to Fill Area Enclosed by Multiple Functions in One Plot

pgfplotstikz-pgf

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?

Best Answer

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