55

I want to hatch the area under a curve (graph of a function) with oblique lines on an interval (to illustrate the function's integral on that interval). This can be done elegantly in gnuplot... enter image description here

...but I simply cannot reproduce this with pgfplots. The only solution I managed to find with google is the use of the patterns tikz library, however it is unacceptibly ugly:

enter image description here

I'm not aware of any way to alter the color, line width and - especially - the distance between the hatching lines when patterns library is employed. Is there any way to set it? (So that I can change it to resemble the gnuplot version.)

Or, should I choose a completely different approach to reproduce the gnuplot-style hatching...?

Also note that

  • pgfplots changes the color of the x-axis to red on the interval (which is not a critical problem, of course, but not elegant).
  • the legend for the filling is much more logical in case of gnuplot. Can I reproduce it with pgfplots?

Here is the code I currently use:

\begin{figure}[ht!]
\centering
\begin{tikzpicture}
    \begin{axis}[xmin=-4,xmax=4,xlabel={z},ymin=0,ymax=1] 
    \addplot[color=red,domain=-4:4,samples=100] {1/sqrt(2*pi)*exp(-x^2/2)};
    \addlegendentry{z}
    \addplot[color=red,fill=red, pattern=north east lines,  domain=0:1,samples=100] {1/sqrt(2*pi)*exp(-x^2/2)} \closedcycle;
    \addlegendentry{Interval}
    \end{axis}
\end{tikzpicture}
\end{figure}
2
  • You say you can do this with gnuplot? Please would you post how? I have been totally unable to find out! Thanks!
    – user49826
    Commented Apr 13, 2014 at 17:13
  • Please do not post comments or questions as an answer to a question.
    – Alexander
    Commented Apr 13, 2014 at 17:19

4 Answers 4

68

You can define your own pattern that can take optional arguments for setting the distance between the lines and the line thickness.

To make sure the axis line stays black, you can set axis on top, which will draw the axis lines last.

And to get the hatch pattern in the legend as well, add the key area legend to the plot:

 \documentclass{article}
    \usepackage{tikz}
    \usetikzlibrary{patterns}
    \usepackage{pgfplots}
    \begin{document}
    \begin{tikzpicture}
    \tikzset{
        hatch distance/.store in=\hatchdistance,
        hatch distance=10pt,
        hatch thickness/.store in=\hatchthickness,
        hatch thickness=2pt
    }

    \makeatletter
    \pgfdeclarepatternformonly[\hatchdistance,\hatchthickness]{flexible hatch}
    {\pgfqpoint{0pt}{0pt}}
    {\pgfqpoint{\hatchdistance}{\hatchdistance}}
    {\pgfpoint{\hatchdistance-1pt}{\hatchdistance-1pt}}%
    {
        \pgfsetcolor{\tikz@pattern@color}
        \pgfsetlinewidth{\hatchthickness}
        \pgfpathmoveto{\pgfqpoint{0pt}{0pt}}
        \pgfpathlineto{\pgfqpoint{\hatchdistance}{\hatchdistance}}
        \pgfusepath{stroke}
    }
    \makeatother

    \begin{axis}[
        xmin=-4,xmax=4,
        xlabel={z},
        ymin=0,ymax=1,
        axis on top,
        legend style={legend cell align=right,legend plot pos=right}] 
    \addplot[color=red,domain=-4:4,samples=100] {1/sqrt(2*pi)*exp(-x^2/2)};
    \addlegendentry{z}
    \addplot+[mark=none,
        domain=0:1,
        samples=100,
        pattern=flexible hatch,
        area legend,
        pattern color=red]{1/sqrt(2*pi)*exp(-x^2/2)} \closedcycle;
    \addlegendentry{Interval 1}
    \addplot+[mark=none,
        domain=-2:-0.5,
        samples=100,
        pattern=flexible hatch,
        hatch distance=5pt,
        hatch thickness=0.5pt,
        draw=blue,
        pattern color=cyan,
        area legend]{1/sqrt(2*pi)*exp(-x^2/2)} \closedcycle;    
        \addlegendentry{Interval 2}
    \end{axis}
\end{tikzpicture}
\end{document}
5
  • @Jake I was wondering, can you easily set the lines to be opposite (like \ versus /?) So that if you overlapped them they would both be easily visible (using thin lines)?
    – Alenanno
    Commented Apr 6, 2013 at 10:47
  • Just for those who wants the lines perfectyle aligned, change {\pgfpoint{\hatchdistance-1pt}{\hatchdistance-1pt}} to 1.5pt in both times.
    – JnxF
    Commented Oct 2, 2013 at 16:48
  • @Jake That is awesome! I was wondering, can you shift the lines ? I would like them to "start" the way I want. Changing the distance doesn't work, they always start the same. I tried changing some numbers, couldn't make it work! Thanks
    – redfiloux
    Commented Apr 2, 2015 at 23:30
  • Ok Got it. If somebody is interested you can find it here : tex.stackexchange.com/questions/54358/…
    – redfiloux
    Commented Apr 2, 2015 at 23:43
  • 1
    Just for the record: If you have more than one flexible hatch you are not able to change the color any more. A solution to this problem is e.g. given at tex.stackexchange.com/a/405505/95441 Commented Dec 11, 2017 at 18:34
19
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{patterns}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\pgfdeclarepatternformonly{north east lines wide}%
   {\pgfqpoint{-1pt}{-1pt}}%
   {\pgfqpoint{10pt}{10pt}}%
   {\pgfqpoint{9pt}{9pt}}%
   {
     \pgfsetlinewidth{0.4pt}
     \pgfpathmoveto{\pgfqpoint{0pt}{0pt}}
     \pgfpathlineto{\pgfqpoint{9.1pt}{9.1pt}}
     \pgfusepath{stroke}
    }

    \begin{axis}[xmin=-4,xmax=4,xlabel={z},ymin=0,ymax=1] 
    \addplot[color=red,domain=-4:4,samples=100] {1/sqrt(2*pi)*exp(-x^2/2)};
    \addlegendentry{z}
    \addplot+[mark=none,domain=0:1,samples=100,%
              pattern=north east lines wide,%
              pattern color=red!50!yellow]%
              {1/sqrt(2*pi)*exp(-x^2/2)}
              \closedcycle;
    \addlegendentry{Interval}
    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

0
16

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{tikz}
    \usetikzlibrary{patterns}
    \usepackage{pgfplots}
    \pgfplotsset{compat=1.10}
    \usepgfplotslibrary{fillbetween}
    \begin{document}
    \begin{tikzpicture}
    \tikzset{
        hatch distance/.store in=\hatchdistance,
        hatch distance=10pt,
        hatch thickness/.store in=\hatchthickness,
        hatch thickness=2pt
    }

    \makeatletter
    \pgfdeclarepatternformonly[\hatchdistance,\hatchthickness]{flexible hatch}
    {\pgfqpoint{0pt}{0pt}}
    {\pgfqpoint{\hatchdistance}{\hatchdistance}}
    {\pgfpoint{\hatchdistance-1pt}{\hatchdistance-1pt}}%
    {
        \pgfsetcolor{\tikz@pattern@color}
        \pgfsetlinewidth{\hatchthickness}
        \pgfpathmoveto{\pgfqpoint{0pt}{0pt}}
        \pgfpathlineto{\pgfqpoint{\hatchdistance}{\hatchdistance}}
        \pgfusepath{stroke}
    }

    \begin{axis}[
        xmin=-4,xmax=4,
        xlabel={z},
        ymin=0,ymax=1,
        axis on top,
        legend style={legend cell align=right,legend plot pos=right}] 

    \addplot[name path=A,color=red,domain=-4:4,samples=100] {1/sqrt(2*pi)*exp(-x^2/2)};
    \addlegendentry{z}

    \path[name path=B] (axis cs:\pgfkeysvalueof{/pgfplots/xmin},0) -- (axis cs:\pgfkeysvalueof{/pgfplots/xmax},0);

    \addplot+[draw,pattern=flexible hatch,pattern color=red]
    fill between[
        of=A and B,
        soft clip={domain=0:1},
    ];
    \addlegendentry{Interval 1}

    \addplot[pattern=flexible hatch,pattern color=cyan,draw=blue,hatch distance=5pt, hatch thickness=0.5pt]
    fill between[
        of=A and B,
        soft clip={domain=-2:-0.5},
    ];
    \addlegendentry{Interval 2}
    \end{axis}
\end{tikzpicture}
\end{document}

This solution re-uses the pattern styles as proposed and written by Jake. However, it simplifies the filling by means of the new features of \usepgfplotslibrary{fillbetween}.

In this case, we assign the name name path=A to the input path. Then, we generate an artificial \path with name B: this \path is not drawn and not filled; it resembles the entire x axis.

Finally, we can generate two \addplot fill between instructions, each with individual styles. The only difference is the soft clip argument: it allows to restrict the fill path to the given domain arguments.

3
  • The pattern covers the tick markings on the axis. Is there a way to put the pattern in the bottom layer, so that the tick marks show?
    – MunHo
    Commented Oct 2, 2015 at 22:37
  • I suppose the most simple way to achieve that effect is to use axis on top. Commented Oct 3, 2015 at 9:09
  • Just for the record: If you have more than one flexible hatch you are not able to change the color any more. A solution to this problem is e.g. given at tex.stackexchange.com/a/405505/95441 Commented Dec 11, 2017 at 18:34
0

It would be a better solution:

\usetikzlibrary{patterns.meta}
\pgfdeclarepattern{
  name=flexible hatch,
  parameters={\hatchdistance,\hatchthickness,\hatchangle},
  bottom left={\pgfpointorigin},
  top right={\pgfpoint{\hatchdistance}{\hatchdistance}},
  tile size={\pgfpoint{\hatchdistance}{\hatchdistance}},
  tile transformation={\pgftransformrotate{\hatchangle}},
  code={
    \begin{pgfscope}
      \pgfsetlinewidth{\hatchthickness}
      \pgfpathmoveto{\pgfpoint{0}{\hatchdistance/2}}
      \pgfpathlineto{\pgfpoint{\hatchdistance}{\hatchdistance/2}}
      \pgfusepath{stroke}
    \end{pgfscope}
  }
}
\tikzset{
  hatch distance/.store in=\hatchdistance,
  hatch distance=6pt,
  hatch thickness/.store in=\hatchthickness,
  hatch thickness=3pt,
  hatch angle/.store in=\hatchangle,
  hatch angle=45,
}

Points are:

  • Use pgfscope to prevent the change of line width from being global
  • the pattern can be rotated; e.g., hatch angle=30
  • hatch distance is the real distance between lines
  • no direct use of \tikz@pattern@color
2
  • Welcome to TeX.SX! Instead of posting a code snippet, it would be better to provide a (full) minimal working example (MWE) so visitors can simply copy/paste the code and see it directly working. Additionally it would be nice to include an image of the code result (as in the other answers. If I would have a wish: Please redo Christian's answer with the patterns.meta library. Commented Jan 19, 2022 at 17:07
  • For the record: The patterns.meta library was first introduced in 2005 with v3.01 and is considered "robust" since 2019 with v3.1.5. Commented Jan 19, 2022 at 17:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .