3

I would like to have two layers behind the background layer: waybackgroundlayer and boundingboxlayer and also use the fillbetween.

The MWE below uses \AxisEnvironmentFig to graph the curves. The * option, which disables the fill between, is used in the second figure where I had to comment out the \DrawBoundingBox.

enter image description here

I would like to be able to use both the fill between and have my two additional layers available to me.

References:

There are a several related questions on this site, but I was not able to get them to work.

Failed Attempts:

From pgfplots: Fill between breaks background layer and Page 410 of the pgfplots manual, I attempted to use

\pgfplotsset{layers/standard/.define layer set={
        waybackgroundlayer, boundingboxlayer, 
        background,
        axis background,axis grid,axis ticks,axis lines,axis tick labels,
        main,
        axis descriptions,axis foreground
    }{
grid style={/pgfplots/on layer=axis grid},
tick style={/pgfplots/on layer=axis ticks},
axis line style={/pgfplots/on layer=axis lines},
label style={/pgfplots/on layer=axis descriptions},
legend style={/pgfplots/on layer=axis descriptions},
title style={/pgfplots/on layer=axis descriptions},
colorbar style={/pgfplots/on layer=axis descriptions},
ticklabel style={/pgfplots/on layer=axis tick labels},
axis background@ style={/pgfplots/on layer=axis background},
3d box foreground style={/pgfplots/on layer=axis foreground},
}}

and also

\pgfplotsset{layers/PetersLayers/.define layer set={
        waybackgroundlayer, boundingboxlayer, background,
        axis background,axis grid,axis ticks,axis lines,axis tick labels,
        main,
        axis descriptions,axis foreground,
    }{/pgfplots/layers/standard},
}
\pgfplotsset{set layers=PetersLayers}

Code:

\documentclass{standalone}
\usepackage{xstring}
\usepackage{xparse}
\usepackage{pgfplots}
\usetikzlibrary{intersections}
\usetikzlibrary{backgrounds}
\usepgfplotslibrary{fillbetween}
\pgfplotsset{compat=newest}


\pgfdeclarelayer{foreground} 
\pgfdeclarelayer{background}
\pgfdeclarelayer{boundingboxlayer}
\pgfdeclarelayer{waybackgroundlayer}
\pgfsetlayers{waybackgroundlayer,boundingboxlayer,background,main,foreground}

%\pgfplotsset{layers/standard/.define layer set={
%        waybackgroundlayer, boundingboxlayer, 
%        background,
%        axis background,axis grid,axis ticks,axis lines,axis tick labels,
%        main,
%        axis descriptions,axis foreground
%    }{
%grid style={/pgfplots/on layer=axis grid},
%tick style={/pgfplots/on layer=axis ticks},
%axis line style={/pgfplots/on layer=axis lines},
%label style={/pgfplots/on layer=axis descriptions},
%legend style={/pgfplots/on layer=axis descriptions},
%title style={/pgfplots/on layer=axis descriptions},
%colorbar style={/pgfplots/on layer=axis descriptions},
%ticklabel style={/pgfplots/on layer=axis tick labels},
%axis background@ style={/pgfplots/on layer=axis background},
%3d box foreground style={/pgfplots/on layer=axis foreground},
%}}

%\pgfplotsset{layers/PetersLayers/.define layer set={
%        waybackgroundlayer, boundingboxlayer, background,
%        axis background,axis grid,axis ticks,axis lines,axis tick labels,
%        main,
%        axis descriptions,axis foreground,
%    }{/pgfplots/layers/standard},
%}
%\pgfplotsset{set layers=PetersLayers}


\newcommand*{\DrawBoundingBox}{%
  \begin{pgfonlayer}{boundingboxlayer}
    \draw [red, ultra thick, fill=yellow!25, use as bounding box]
        ([shift={(-5pt,-5pt)}]current bounding box.south west)
            rectangle
        ([shift={(5pt,+5pt)}]current bounding box.north east);
  \end{pgfonlayer}%
}

\NewDocumentCommand{\AxisEnvironmentFig}{% https://tex.stackexchange.com/a/353688/4301
    s% #1=* means don't apply "fill between"
}{%
    \begin{axis}[
        xmin=-4,    xmax=6,
        ymin=-5,    ymax=6,
        axis lines=middle,
        axis equal image=true,
        axis on top,
        no markers,
        smooth,
        domain=-6:6,
        %set layers=PetersLayers,
    ]

        %% simplest is reformulate the root function to a parabola ...
        %\addplot+ [blue, thick, name path=curve] {sqrt(2*x+6)};
        % ... and draw it as parametric plot
        \addplot+ [blue, thick, name path=curve] (0.5*x^2-3, x);

        \addplot [red, thick, name path=line]  {x-1};

        \IfBooleanF{#1}{% <--- Modification from 353688
            % then you only want to fill the closed segment which number 1
            % (the counting starts from 0)
            % to to so you don't want to fill anything else
            \addplot [fill=none] fill between [
                of=curve and line,
                % to be able to apply styles to each segment
                split,
                % then provide the style to fill the named segment
                every segment no 1/.style={
                    fill=green!50,
                },
            ];
        }%
    \end{axis}
}

\begin{document}
    \begin{tikzpicture}
        \AxisEnvironmentFig*
        \DrawBoundingBox
    \end{tikzpicture}
    ~%% The following does not work as it uses "fill between"
    \begin{tikzpicture}
        \AxisEnvironmentFig
        %\DrawBoundingBox%% <--- What do I need to do above so I can uncomment this ???
    \end{tikzpicture}
\end{document}

1 Answer 1

4

Your attempt was totally right, but unfortunately you missed to declare/set the layer pre main to which by default the fill between stuff is moved. And you missed that, because it is also missing in the manual where you copied the .define layer set stuff from. (I already took a note to correct that.)

After doing this, everything works almost fine, because you copied the layer set from default. That would result to the filled area being over the axis lines, ticks and ticklabels, which most likely is not what you want. To prevent that you have several options.

  1. Change the default layer to which fill between is written that is below all that stuff, e.g. by adding fill between/on layer=axis background to the axis options.
  2. Use the axis on top layer order when you define your own layer set (which I have done here).

% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{xparse}
\usepackage{pgfplots}
    \usetikzlibrary{pgfplots.fillbetween}
    \pgfplotsset{
        compat=1.16,
        % switched layers to the default of `axis on top` and added missing
        % layer `pre main` (which is present in the code, but not in the manual)
        layers/PetersLayers/.define layer set={
            waybackgroundlayer, boundingboxlayer,
            axis background,
            pre main,       % <-- added
            main,
            axis grid,axis ticks,axis lines,axis tick labels,
            axis descriptions,axis foreground,
        }{/pgfplots/layers/axis on top},
        set layers=PetersLayers,
    }

\newcommand*{\DrawBoundingBox}{
  \begin{pgfonlayer}{boundingboxlayer}
    \draw [red, ultra thick, fill=yellow!25, use as bounding box]
        ([shift={(-5pt,-5pt)}]current bounding box.south west)
            rectangle
        ([shift={(5pt,+5pt)}]current bounding box.north east);
  \end{pgfonlayer}
}

\NewDocumentCommand{\AxisEnvironmentFig}{% https://tex.stackexchange.com/a/353688/4301
    s% #1=* means don't apply "fill between"
}{%
    \begin{axis}[
        xmin=-4,    xmax=6,
        ymin=-5,    ymax=6,
        axis lines=middle,
        axis equal image=true,
        no markers,
        smooth,
        domain=-6:6,
    ]

        %% simplest is reformulate the root function to a parabola ...
        %\addplot+ [blue, thick, name path=curve] {sqrt(2*x+6)};
        % ... and draw it as parametric plot
        \addplot+ [blue, thick, name path=curve] (0.5*x^2-3, x);

        \addplot [red, thick, name path=line]  {x-1};

        \IfBooleanF{#1}{% <--- Modification from 353688
            % then you only want to fill the closed segment which number 1
            % (the counting starts from 0)
            % to to so you don't want to fill anything else
            \addplot [fill=none] fill between [
                of=curve and line,
                % to be able to apply styles to each segment
                split,
                % then provide the style to fill the named segment
                every segment no 1/.style={
                    fill=green!50,
                },
            ];
        }
    \end{axis}
}

\begin{document}
    \begin{tikzpicture}
        \AxisEnvironmentFig*
        \DrawBoundingBox
    \end{tikzpicture}
    ~
    \begin{tikzpicture}
        \AxisEnvironmentFig
        \DrawBoundingBox
    \end{tikzpicture}
\end{document}

image showing the result of above code

10
  • Thanks, this looks great. But, has an issue if I manually specify axis on top as one of the parameters. What adjustments need to be made to allow for both specifying axis on top` and not specifying it? Aug 30, 2019 at 22:36
  • Also, why is the /pgfplots/layers/axis on top not just /pgfplots/layers/standard? If I understand correctly, that portion is just specifying which layer each item goes on. Its the order of the layers that matter and is that is specified in the first parameter to \pgfplotsset. I am trying to understand this further as in my actual use case I am missing the axis ticks, axis lines and axis tick labels when I include the bounding box (after using fill between). Aug 31, 2019 at 4:23
  • Sorry, but I don't understand that question and your problem. I guess for the latter that when you are using layers/standard that then the fill between stuff is over the axis stuff. That is why I used the order of layers from axis on top. Aug 31, 2019 at 6:49
  • First Question: Try adding axis on top option to the axis environment. Aug 31, 2019 at 6:59
  • Not in above comments: is it possible to restrict these new .define layer to every fill between plot as per p. 439 of the current manual? This will at least move my problem (second comment above, but don't have a MWE to reproduce it yet) that I am having to only when 'fill between' is applied? Aug 31, 2019 at 6:59

You must log in to answer this question.

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