# Fill the area determined by two pgfplots graphs

I need to fill the region determined by two (Gaussian) curves and the right red line (the region is brushed in green in the figure below). I also wonder what is the best way to draw vertical line which goes through the intersection of both graphs (the left red line on the figure).

Any pointers would be greatly appreciated.

My initial attemt is pasted below.

\documentclass{standalone}
\usepackage{pgfplots}

\begin{document}

\pgfmathdeclarefunction{dnorm}{2}{%
\pgfmathparse{1/(#2*sqrt(2*pi))*exp(-((x-#1)^2)/(2*#2^2))}%
}

\begin{tikzpicture}
\begin{axis}[domain=0:12, samples=100, height=5cm, width=10cm]
% Fill aread under the curves
\addplot [fill=red!20, draw=none, domain=0:6] {dnorm(6.5,1.5)} \closedcycle;
\addplot [fill=blue!20, draw=none, domain=6:10] {dnorm(4,1)} \closedcycle;
% Draw curves
\end{axis}
\end{tikzpicture}

\end{document}


My solution

A picture is worth a thousand words. Code is pasted below.

\documentclass{article}
\usepackage{tkz-fct}
\usetikzlibrary{intersections}

\begin{document}

\tikzset{
name plot/.style={every path/.style={name path global=#1}}
}

% Extract coordinates for point X
\makeatletter
\newcommand{\gettikzxy}[3]{%
\tikz@scan@one@point\pgfutil@firstofone#1\relax
\edef#2{\the\pgf@x}%
\edef#3{\the\pgf@y}%
}
\makeatother

% Dimlines
\def\Dimline[#1][#2][#3][#4]{
\begin{scope}[thin, >=stealth'] % redefine as flechas
\draw let \p1=#1, \p2=#2, \n0={veclen(\x2-\x1,\y2-\y1)} in [|<->|,
decoration={markings,mark=at position .5 with {\node[#3] at (0,0)
{#4};},
},
postaction=decorate] #1 -- #2 ;
\end{scope}
}

\begin{tikzpicture}[scale=1,font=\small]
\tkzInit[xmin=0,xmax=12,ymin=0,ymax=.3,ystep=.05]
% Draw coordinates
\draw[>=stealth', <->] (0,6) node[above] {$y$} -- (0,0) --  (12.5,0) node[right] {$x$};
% Draw functions and areas
\tkzFct[name plot=A,thick,color=red,domain=0:12]{1/(1.5*sqrt(2*pi))*exp(-((x-4.5)**2)/(2*1.5**1))}
\tkzDrawArea[opacity=.3,color=blue,domain = 7:12]
\tkzFct[name plot=B,thick,color=blue,domain=0:12]{1/(2*sqrt(2*pi))*exp(-((x-7)**2)/(2*2**1))}
\tkzDrawArea[opacity=.3,color=red,domain=0:7]
\tkzDrawAreafg[between=b and a,opacity=.3,color=green,domain = 0:7]
% Intersection between curves
\path [name intersections={of=A and B,by=C}];
% Extract coordinates of C
\gettikzxy{(C)}{\cx}{\cy}
% Vertical lines
\draw [thick,dashed, black] (\cx,0) -- (\cx,5.5) node [above] {$x_{0}$};
\draw [thick,dashed, black] (7,0) -- (7,5.5) node [above] {$\hat{x}$};
% Define regions
\Dimline[($(0,0)+(0,-.6)$)][($(7,0)+(0,-.6)$)][above,black][$\mathcal{R}_{1}$];
\Dimline[($(7,0)+(0,-.6)$)][($(12,0)+(0,-.6)$)][above, black][$\mathcal{R}_{2}$];
\end{tikzpicture}

\end{document}

-
Maybe tex.stackexchange.com/q/34102/18674 could help you with the intersection area. About the vertical lines: is your question about just drawing vertical lines or should they be calculated from the intersection automatically? –  Benedikt Bauer Nov 20 '12 at 21:13
About vertical line: need to draw line which is perpendicular to x-axis and goes through intersection point. –  Andrej Nov 21 '12 at 6:02
@Andrej: Since the solution you ended up using is quite different from mine (using tkz-fct, the \gettikzxy macro...), I think it would be good if you could add (and possibly accept) an answer of your own. It's generally preferred to have code on this site itself instead of referring to an external hosting service. –  Jake Nov 21 '12 at 18:46

Since PGFPlots version 1.10 came out, there's a much more elegant way to do this. See Christian Feuersänger's answer.

For pre-1.10 versions of PGFPlots:

You can fill the areas above a curve f and below a curve g by first plotting f and then stacking min(g-f, 0) on top. That expression will become 0 whenever f<=g, and g-f whenever f>g.

To get the vertical lines, you can use the intersections approach from How do I name a plot in tikz and use it for intersections? together with How can I add a zero line to a plot?

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{intersections}

\begin{document}

\pgfmathdeclarefunction{dnorm}{2}{%
\pgfmathparse{1/(#2*sqrt(2*pi))*exp(-((x-#1)^2)/(2*#2^2))}%
}

\begin{tikzpicture}
\begin{axis}[
domain=0:12,
samples=101,
height=5cm,
width=10cm
]

% Fill aread under both curves, start stacking
fill=yellow,
draw=none,
domain=0:6,
stack plots=y
] {min(dnorm(4,1),dnorm(6.5,1.5)) } \closedcycle;

% Stack difference between two curves on top, but only where the second curve is higher
fill=orange,
draw=none,
domain=0:6,
stack plots=y
] {max( dnorm(6.5,1.5) - dnorm(4,1),0)} \closedcycle;

% Fill tail of first curve (without stacking)
fill=cyan,
draw=none,
domain=6:12
] {dnorm(4,1)} \closedcycle;

% Draw curves
\addplot [thin, smooth, name path global=first] {dnorm(4,1)};
\addplot [thin, smooth, name path global=second] {dnorm(6.5,1.5)};

% Draw vertical line:
\draw [red, thick] ({rel axis cs:0,0}-|{axis cs:6,0}) -- ({rel axis cs:0,1}-|{axis cs:6,0});
\draw [red, thick, name intersections={of={first and second}}] ({rel axis cs:0,0}-|intersection-1) -- ({rel axis cs:0,1}-|intersection-1);
\end{axis}
\end{tikzpicture}

\end{document}

-
Nice, nice, nice! –  Andrej Nov 21 '12 at 15:54

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:

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots}

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

\begin{document}

\pgfmathdeclarefunction{dnorm}{2}{%
\pgfmathparse{1/(#2*sqrt(2*pi))*exp(-((x-#1)^2)/(2*#2^2))}%
}

\begin{tikzpicture}

\def\startx{0}
\def\endx{12}
\def\verticalbar{6}

\begin{axis}[
domain=\startx:\endx,
samples=101,
height=5cm,
width=10cm
]

% Draw curves

% compute + label the part below the two plots:
\path[name path=lower,
%thick,draw=red,
intersection segments={
of=g4 and g6.5,
sequence=B0 -- A1,
}
];

% Draw vertical separator line:
\draw [red, thick] ({rel axis cs:0,0}-|{axis cs:\verticalbar,0}) -- ({rel axis cs:0,1}-|{axis cs:\verticalbar,0});

% label the x axis:
\path[name path=axis] (axis cs:\startx,0) -- (axis cs:\endx,0);

% generate fill paths:
\addplot[red!30]   fill between[of=lower and axis,soft clip={domain=-3:\verticalbar}];
\addplot[blue!30]  fill between[of=lower and axis,soft clip={domain=\verticalbar:20}];
\addplot[green!30] fill between[of=g6.5 and lower,soft clip={domain=-3:\verticalbar}];

\end{axis}
\end{tikzpicture}
\end{document}


The example consists of the two input paths (labelled g4 and g6.5, respectively). Furthermore, it contains \path instruction to compute the "part below the intersection of both", labelled name path=lower. The fact that it is merely a \path means that it won't be drawn - it is simply generated and stored under the label.

The key intersection segments is a new feature of pgfplots 1.10: it allows to concatenate pieces resulting from an intersection. The syntax B0 means to take the first (0th) segment of the second argument in g4 and g6.5, i.e. it is the first segment of g6.5. The -- means "connect with lineto" and A1 means to take the second (1st) segment of the first argument in g4 and g6.5, that is: it connects with the second segment of g4.

The red line is just as before, the only exception is that I introduced a constant \verticalbar defined as 6.

Then, we have a further \path instruction which labels the x axis - more specifically, a part of the x axis. Finally, we have three \addplot fill between instructions, one for the red, one for the blue and one for the green region. The key soft clip restricts the input paths to the domain in question.

-