pgf-tikz / pgfplots

pgfplots - A TeX package to draw normal and/or logarithmic plots directly in TeX in two and three dimensions with a user-friendly interface and pgfplotstable - a TeX package to round and format numerical tables. Examples in manuals and/or on web site.
http://pgfplots.sourceforge.net/
200 stars 34 forks source link

Polar plots with y coord trafo/y coord inv trafo leads to wrong output when using floating point computations #360

Open BambOoxX opened 4 years ago

BambOoxX commented 4 years ago

This problem is related to this stackexchange question Polar plot with small values and coordinate transformations leads to a “Dimension too large error”.

Here is a repost of the original question.

While plotting polar axes, I faced an issue when transforming small quantities with the y coord trafo/y coord inv trafo options.

My plots are basically sine functions show in the polar domain. As an example take the following cosine cos(3\x). This function has positive and negative values and is plotted as expected in an axis environment.

enter image description here

Now if one wants to plot this very same function inside a polaraxis environment, here is what comes out :

enter image description here

Basically, negative values are handled as a 180° phase shift, instead of being simply shown as a negative value at the defined angular coordinate.

This behavior can be circumvented with some well-chosen y coord trafo/y coord inv trafo. In this very case,

y coord trafo/.code=\pgfmathparse{#1+2},
y coord inv trafo/.code=\pgfmathparse{#1-2},

works just fine.

enter image description here

However, if some small values have to be handled, say around 1e-6 amplitude instead of 1 as in the above examples, the computation fails due to precision errors. These problems should be solvable through the fpu unit, but I can't figure the correct sequence. I tried e.g.

y coord trafo/.code={\pgfkeys{/pgf/fpu=true}\pgfmathparse{#1+2e-6}\pgfkeys{/pgf/fpu=false}},
y coord inv trafo/.code={\pgfkeys{/pgf/fpu=true}\pgfmathparse{#1-2e-6}\pgfkeys{/pgf/fpu=false}},

but this leads to illegal unit of measure errors.

Here is the MWE to reproduce the figures and the problem once the commented part is reactivated.

\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\usepgfplotslibrary{polar}
\usepackage{amsmath}
\begin{document}
\begin{tikzpicture}
    \begin{axis}[%
            xmin=0,
            xmax=360,
            ymin=-2,
            ymax=2,
            domain = 0:360,
        ]
        \addplot+ ({\x},{cos(3*\x)});
    \end{axis}
\end{tikzpicture}
\begin{tikzpicture}
    \begin{polaraxis}[%
            xmin=0,
            xmax=360,
            ymin=-2,
            ymax=2,
            domain = 0:360,
        ]
        \addplot+ ({\x},{cos(3*\x)});
    \end{polaraxis}
\end{tikzpicture}

\begin{tikzpicture}
    \begin{polaraxis}[%
            xmin=0,
            xmax=360,
            ymin=-2,
            ymax=2,
            y coord trafo/.code=\pgfmathparse{#1+2},
            y coord inv trafo/.code=\pgfmathparse{#1-2},
            domain = 0:360,
        ]
        \addplot+ ({\x},{cos(3*\x)});
    \end{polaraxis}
\end{tikzpicture}

% Not working
% \begin{tikzpicture}
%     \begin{polaraxis}[%
%             xmin=0,
%             xmax=360,
%             ymin=-2e-6,
%             ymax=2e-6,
%             y coord trafo/.code={\pgfmathparse{#1+2e-6}},
%             y coord inv trafo/.code={\pgfmathparse{#1-2e-6}},
%             domain = 0:360,
%         ]
%         \addplot+ ({\x},{1e-6*cos(3*\x)});
%     \end{polaraxis}
% \end{tikzpicture}

\end{document}

Based on this, a proposal was to replace the \pgfmathparse with a \pgfmathparsFPU macro defined as

\newcommand{\pgfmathparseFPU}[1]{\begingroup%
  \pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
  \pgfmathparse{#1}%
  \pgfmathsmuggle\pgfmathresult\endgroup}

However, this leads to wrong output in the ticklabels.

BambOoxX commented 4 years ago

Maybe this could be the occasion to add a setting in pgfplots in order to chose how negative values are handled in polaraxis , e.g. with the data cs key or simply by testing against negative ymin values.