1

Here is a minimal nonworking example:

% preamble
\documentclass[class=minimal,border=0pt]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}
\usepgfplotslibrary{fillbetween}

\begin{document}

% want to use this environment. Doesn't work with fill between.

\newenvironment{myaxes}
{%
\begin{axis}[% here are many options in a real case
    ]
}
{%
\end{axis}
}

% a trivial plotting command which is identical everywhere

\newcommand{\myplot}{
    \addplot [domain=-1:1, name path = func] {- x*x + 1};
    \addplot [draw=none, name path = xaxis] {0};
    \addplot [red] fill between [of = xaxis and func ];
}

% this picture is fine

\begin{tikzpicture}
\begin{axis}
\myplot
\end{axis}
\end{tikzpicture}

% this is drawn, but is not filled.

\begin{tikzpicture}
\begin{myaxes}
\myplot
\end{myaxes}
\end{tikzpicture}

% this workaround works

\newcommand{\beginmyaxis}{
\begin{axis}[% options here
    ]
}

% name 'endmyaxis' doesn't work, but it's not most important
\newcommand{\emyaxis}{
\end{axis}
}

\begin{tikzpicture}
\beginmyaxis
\myplot
\emyaxis
\end{tikzpicture}

\end{document}

the results of fillbetween

It seems that pgfplots and my environment work, the issue is only with fillbetween.

I'm using pgfplots 1.12.

My primary question is why this happens? Is it just a bug, or don't I understand something deep. I've read pgfplots recent change log about fillbetween, but this issue is not there. I won't be surprised if it's a bug, then it would be nice to tell about that to others.

It would be interesting to see other workarounds.

My original intention was to create several plots that vary in some parameters and decorations, but have much in common that I wanted to define as an environment (seems more (La)TeXnical than open and closing commands).

  • 1
    The TikZ way is to collect options in keys \pgfplotsset{my style/.style={....}} and using the normal axis environment. – percusse Apr 28 '15 at 21:03
  • @percusse thanks! But I wanted to use the environment not only for options, but also for drawing some things - does it correspond to style? – Yaroslav Nikitenko Apr 28 '15 at 21:33
2

This is due to an additional \begingroup / \endgroup pair which is introduced by \newenvironment combined with deep magic which communicates the set of graphics layers from the axis to the tikzpicture.

There are basically three ways to solve it:

1] Activate layered graphics manually before your axis:

\documentclass[class=minimal,border=0pt]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}
\usepgfplotslibrary{fillbetween}

\newenvironment{myaxes}
{%
    \begin{axis}[% here are many options in a real case
        ]
}
{%
    \end{axis}%
}

\newcommand{\myplot}{
    \addplot [domain=-1:1, name path = func] {- x*x + 1};
    \addplot [draw=none, name path = xaxis] {0};
    \addplot [red] fill between [of = xaxis and func ];
}
\begin{document}
\begin{tikzpicture}
\pgfplotsset{set layers}
\begin{myaxes}
\myplot
\end{myaxes}
\end{tikzpicture}

\end{document}

2] Use deep magic which depends on internals of PGF/pgfplots:

\documentclass[class=minimal,border=0pt]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}
\usepgfplotslibrary{fillbetween}

\newenvironment{myaxes}
{%
    \begin{axis}[% here are many options in a real case
        ]
}
{%
    \end{axis}%
    \expandafter\aftergroup\csname pgf@restore@layerlist@from@global\endcsname
}

\newcommand{\myplot}{
    \addplot [domain=-1:1, name path = func] {- x*x + 1};
    \addplot [draw=none, name path = xaxis] {0};
    \addplot [red] fill between [of = xaxis and func ];
}
\begin{document}
\begin{tikzpicture}
\begin{myaxes}
\myplot
\end{myaxes}
\end{tikzpicture}

\end{document}

3] use

\begin{tikzpicture}
\myaxes
\myplot
\endmyaxes
\end{tikzpicture}

Instead of the LaTeX environment (these macros are defined by \newenvironment).


Explanation: fill between implicitly activates layered graphics such that the filled region is under the delimiting plots although it has been defined after them in the code. This set of layered graphics needs to be communicated to the enclosing tikzpicture, and that is (unfortunately) subject to TeX grouping constructs: every \endgroup clears such lists. The solution by PGF/pgfplots appears to work for standard cases -- and failed in this case.

That means that the picture would also work if you would write fill between[on layer={}] to disable the extra layer (but it would look differently).

Is this a bug? I don't know, honestly... perhaps it should be fixed somehow.

  • Many thanks for the thorough answer! Do I understand right that there is no big difference between putting \newenvironment and \newcommand inside the preamble and inside the \document body? – Yaroslav Nikitenko May 1 '15 at 8:08
  • If there is indeed some important (even though subtle) difference, I may ask a separate question, so that it's not lost in commentaries here. – Yaroslav Nikitenko May 1 '15 at 8:13
  • 1
    I believe there is no difference from a technical point of view. It is just a best-practise to put macro definitions into the preamble, especially if they contain @ characters. – Christian Feuersänger May 1 '15 at 12:40

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.