6

I want to shade the area of overlap for adjacent normal curves, shown in the lower graph. I can get shading between the first two curves but not for subsequent curves. I need shading at overlapping areas indicated by the arrows. I applied the "logic" of the first fill for the subsequent curves but that does not work.

The arrows and letters in the example image are not part of the MWE.

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{ticks=none}
\pgfplotsset{compat=1.7}

\usepgfplotslibrary{fillbetween}

\pgfmathdeclarefunction{gauss}{2}{%normal distribution where #1 = mean and #2 = sd}
    \pgfmathparse{exp(-((x-#1)^2)/(2*#2^2))}%
}

\pgfplotsset{baseplot/.style={%
    no markers, 
    domain=1:4.5, 
    samples=100,
    smooth,
    axis lines*=left,
    height=5cm, width=12cm,
    enlargelimits=upper, clip=false, axis on top,
    xlabel = near ticks,
    xlabel={Resource}
}}

\begin{document}

\begin{tikzpicture}
  \begin{axis}[baseplot]
  \addplot+[name path=A]{gauss(2.7,0.4)};
  \addplot+[name path=B]{gauss(3.2,0.4)};
  \fill[gray!20, intersection segments ={of= B and A}];
\end{axis}
\end{tikzpicture}

\vspace*{3\baselineskip}

\begin{tikzpicture}
  \begin{axis}[baseplot]
  \addplot+[name path=A]{gauss(1.7,0.15)};
  \addplot+[name path=B]{gauss(2.2, 0.15)};
  \addplot+[name path=C]{gauss(2.7, 0.15)};
  \addplot+[name path=D]{gauss(3.2, 0.15)};
  \addplot+[name path=E]{gauss(3.7, 0.15)};
  \fill[gray!20, intersection segments ={of= B and A}];
  \fill[gray!20, intersection segments ={of= C and B}];
  \fill[gray!20, intersection segments ={of= D and C}];
  \fill[gray!20, intersection segments ={of= E and D}];
\end{axis}
\end{tikzpicture}

\end{document}

example

9

I think your case doesn't work as expected, because you draw all Gaussian plots in the full domain (from 1 to 4.5) and so a lot of points are very near together (at y = 0) which I think makes it really hard for TikZ/PGFPlots to calculate the intersections.

When you provide a unique domain to each \addplot this has two advantages.

  1. The lines near y = 0 don't "overlap" any more and thus the "real" intersection points can be found much easier, and
  2. by providing a unique domain to each \addplot you will either get a much more smooth plot with the given samples or you can decrease the samples.

For more details have a look at the comments in the code.

% used PGFPlots v1.14
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
    \usepgfplotslibrary{fillbetween}
    \pgfplotsset{
        compat=1.3,
        baseplot/.style={
            width=12cm,
            height=5cm,
            axis lines*=left,
            axis on top,
            enlargelimits=upper,
            xlabel={Resource},
            ticks=none,
            no markers,
            samples=100,
            smooth,
        },
        /pgf/declare function={
            % normal distribution where \mean = mean and \stddev = sd}
            gauss(\mean,\stddev)=exp(-((x-\mean)^2)/(2*\stddev^2));
        },
    }
    % to simplify the input, which repeats all the time, create a command
    % here #1 = `name path', #2 = `\mean', #3 = `\stddev'
    % the idea is that the gauss values are almost zero after 4 standard
    % deviations and so the `samples' can be better used in that ±4 standard
    % deviation range around the mean value
    % (this has the positive side effect that the lines of two neighboring
    %  gauss plots don't overlap in the "zero" range and thus makes it
    %  much easier for TikZ/PGFPlots to identify the "real" intersections.)
    \newcommand*\myaddplot[3]{
        \addplot+ [name path=#1,domain=#2-4*#3:#2+4*#3] {gauss(#2,#3)};
    }
\begin{document}
    \begin{tikzpicture}
        \begin{axis}[
            baseplot,
            % activate layers
            set layers,
        ]
            \myaddplot{A}{1.7}{0.15}
            \myaddplot{B}{2.2}{0.15}
            \myaddplot{C}{2.7}{0.15}
            \myaddplot{D}{3.2}{0.15}
            \myaddplot{E}{3.7}{0.15}

            % draw the "fill between" stuff on a lower layer
            % (otherwise half of the `\addplot' lines with be overdrawn
            %  by the fills)
            \pgfonlayer{pre main}
                \fill[gray!20, intersection segments={of=B and A}];
                \fill[gray!20, intersection segments={of=C and B}];
                \fill[gray!20, intersection segments={of=D and C}];
                \fill[gray!20, intersection segments={of=E and D}];
            \endpgfonlayer
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of above code

3
  • Your answer was enlightening and also greatly sped up the compilation time by reducing the calculation time. Thank you. Nov 13 '16 at 14:55
  • Your answer inspired me to ask one question; is it possible to easily replace my hobby curve here with Gaussian one, or will it take some effort to do so?
    – Diaa
    Jun 28 '18 at 9:15
  • @Diaa, I don't think that I get your question right. But in general you can replace a path by a function, of course. But after having a short look at your question I don't know what exactly the gaussian curve/function would be good for. Jun 28 '18 at 11:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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