2

I constructed a macro to annotate slopes of graphs by means of triangles in a loglogaxis. It works fine for small slopes, but for large slopes I get a Dimension too large error.

Minimum working example:

\documentclass[margin=1cm]{standalone}
\usepackage{amsmath}
\usepackage{pgfplots}

\pgfplotsset{compat=newest}

\usetikzlibrary{calc}

%%% START MACRO FOR ANNOTATION OF TRIANGLE WITH SLOPE %%%.
\newcommand{\logLogSlopeTriangle}[5]
{
    % #1. Relative offset in x direction.
    % #2. Width in x direction, so xA-xB.
    % #3. Relative offset in y direction.
    % #4. Slope d(y)/d(log10(x)).
    % #5. Plot options.

    \pgfplotsextra
    {
        \pgfkeysgetvalue{/pgfplots/xmin}{\xmin}
        \pgfkeysgetvalue{/pgfplots/xmax}{\xmax}
        \pgfkeysgetvalue{/pgfplots/ymin}{\ymin}
        \pgfkeysgetvalue{/pgfplots/ymax}{\ymax}    

        % Calculate auxilliary quantities.
        \pgfmathsetmacro{\xA}{(exp(\xmin))^(1-#1)*(exp(\xmax))^#1}
        \pgfmathsetmacro{\yA}{(exp(\ymin))^(1-#3)*(exp(\ymax))^#3}
        \pgfmathsetmacro{\xB}{(exp(\xmin))^(1-(#1-#2))*(exp(\xmax))^(#1-#2)}
        \pgfmathsetmacro{\yB}{\yA}
        \pgfmathsetmacro{\xC}{\xA}
        \pgfmathsetmacro{\yC}{\yA/(\xB^#4)*\xA^#4}

        % Define coordinates for \draw.
        \coordinate (A) at (axis cs:\xA,\yA);
        \coordinate (B) at (axis cs:\xB,\yB);
        \coordinate (C) at (axis cs:\xC,\yC);

        % Draw slope triangle.
        \draw[#5]   (A)-- node[pos=0.5,anchor=north] {1}
                    (B)-- 
                    (C)-- node[pos=0.5,anchor=west] {#4}
                    cycle;
    }
}
%%% END MACRO FOR ANNOTATION OF TRIANGLE WITH SLOPE %%%.

\begin{document}
    \begin{tikzpicture}
        \begin{loglogaxis}
        [
            xlabel=$x$,
            ylabel style={rotate=-90},
            ylabel=$y$,
            grid=major,
            clip=false
        ]
            \addplot[blue,line width=1pt,domain=10^1:10^2] {sqrt(x)};
            \addplot[red,line width=1pt,domain=10^1:10^2] {x};
            %\addplot[green!75!black,line width=1pt,domain=10^1:10^2] {x^3}; % RESULTS IN A 'DIMENSION TOO LARGE ERROR. HOW DO I FIX THIS?'

            \logLogSlopeTriangle{0.9}{0.1}{0.1}{0.5}{blue};
            \logLogSlopeTriangle{0.75}{0.1}{0.1}{1}{red};
            %\logLogSlopeTriangle{0.6}{0.1}{0.1}{3}{green!75!black}; % RESULTS IN A 'DIMENSION TOO LARGE ERROR. HOW DO I FIX THIS?'
        \end{loglogaxis}
    \end{tikzpicture}
\end{document}

Result:

Uncommenting the \addplot ... {x^3} and its corresponding annotation \logLogSlopeTriangle{...}, I get the Dimension too large error.

How do I fix this?

Adriaan
  • 3,675
  • 2
  • 21
  • 41
  • 2
    You can't fix it. The cubic plot changes the y axis limits from 1 to a million. Hence the current triangles become practically straight lines. And TikZ tries to find the mid point of the vertical side (that involves inverting the length the side which leads to arithmetic overflow). You really need to find a different way to present this information if it is really needed (independent from the data). As a worst case solution put it below left of the top corner instead of pos key. – percusse May 18 '15 at 10:27
  • @percusse I don't fully understand where this arithmetic overflow takes place. In with operation, that is. You say it can't be fixed, but isn't changing to relative axis coordinates perhaps an option, so rel axis cs instead of axis cs? In this way, the dimensions need not be so large. What do you think? – Adriaan May 18 '15 at 11:04
  • I was too quick to find the source. It's due to your computations that uses TeX arithmetic instead of pgfplots parsing of the numbers. Here exp(\ymax) is e^15.08112 and that is way too big for TeX. You can switch to fpu library for handling big numbers but still rel axis cs or axis direction cs is a better way indeed. – percusse May 18 '15 at 11:12
  • @percusse I solved the issue by using relative coordinates with rel axis cs, see my answer below. I hope you like it. – Adriaan May 19 '15 at 09:48

1 Answers1

2

Using relative coordinates instead of absolute coordinates is the solution. Accordingly, rel axis cs is used instead of axis cs.

It involves quite some math to derive an expression for \yCrel without using \yC, but this is the result (see code) and it works without giving the Dimension too large error.

\documentclass[margin=1cm]{standalone}
\usepackage{amsmath}
\usepackage{pgfplots}

\pgfplotsset{compat=newest}

\usetikzlibrary{calc}

%%% START MACRO FOR ANNOTATION OF TRIANGLE WITH SLOPE %%%.
\newcommand{\logLogSlopeTriangle}[5]
{
    % #1. Relative offset in x direction.
    % #2. Width in x direction, so xA-xB.
    % #3. Relative offset in y direction.
    % #4. Slope d(y)/d(log10(x)).
    % #5. Plot options.

    \pgfplotsextra
    {
        \pgfkeysgetvalue{/pgfplots/xmin}{\xmin}
        \pgfkeysgetvalue{/pgfplots/xmax}{\xmax}
        \pgfkeysgetvalue{/pgfplots/ymin}{\ymin}
        \pgfkeysgetvalue{/pgfplots/ymax}{\ymax}

        % Calculate auxilliary quantities, in relative sense.
        \pgfmathsetmacro{\xArel}{#1}
        \pgfmathsetmacro{\yArel}{#3}
        \pgfmathsetmacro{\xBrel}{#1-#2}
        \pgfmathsetmacro{\yBrel}{\yArel}
        \pgfmathsetmacro{\xCrel}{\xArel}
        %\pgfmathsetmacro{\yCrel}{ln(\yC/exp(\ymin))/ln(exp(\ymax)/exp(\ymin))} % REPLACE THIS EXPRESSION WITH AN EXPRESSION INDEPENDENT OF \yC TO PREVENT THE 'DIMENSION TOO LARGE' ERROR.

        \pgfmathsetmacro{\lnxB}{\xmin*(1-(#1-#2))+\xmax*(#1-#2)} % in [xmin,xmax].
        \pgfmathsetmacro{\lnxA}{\xmin*(1-#1)+\xmax*#1} % in [xmin,xmax].
        \pgfmathsetmacro{\lnyA}{\ymin*(1-#3)+\ymax*#3} % in [ymin,ymax].
        \pgfmathsetmacro{\lnyC}{\lnyA+#4*(\lnxA-\lnxB)}
        \pgfmathsetmacro{\yCrel}{\lnyC-\ymin)/(\ymax-\ymin)} % THE IMPROVED EXPRESSION WITHOUT 'DIMENSION TOO LARGE' ERROR.

        % Define coordinates for \draw. MIND THE 'rel axis cs' as opposed to the 'axis cs'.
        \coordinate (A) at (rel axis cs:\xArel,\yArel);
        \coordinate (B) at (rel axis cs:\xBrel,\yBrel);
        \coordinate (C) at (rel axis cs:\xCrel,\yCrel);

        % Draw slope triangle.
        \draw[#5]   (A)-- node[pos=0.5,anchor=north] {1}
                    (B)-- 
                    (C)-- node[pos=0.5,anchor=west] {#4}
                    cycle;
    }
}
%%% END MACRO FOR ANNOTATION OF TRIANGLE WITH SLOPE %%%.

\begin{document}
    \begin{tikzpicture}
        \begin{loglogaxis}
        [
            xlabel=$x$,
            ylabel style={rotate=-90},
            ylabel=$y$,
            legend style=
            {
                at={(1,1)},
                anchor=north west,
                draw=none,
                fill=none
            },
            legend cell align=left,
            grid=major,
            clip=false
        ]
            \addplot[blue,line width=1pt,domain=10^1:10^4] {sqrt(x)};
            \addplot[red,line width=1pt,domain=10^1:10^4] {x};
            \addplot[green!75!black,line width=1pt,domain=10^1:10^4] {x^2};
            \addplot[brown,line width=1pt,domain=10^1:10^4] {x^3};

            \logLogSlopeTriangle{0.9}{0.1}{0.16}{0.5}{blue};
            \logLogSlopeTriangle{0.9}{0.1}{0.29}{1}{red};
            \logLogSlopeTriangle{0.9}{0.1}{0.53}{2}{green!75!black};
            \logLogSlopeTriangle{0.9}{0.1}{0.79}{3}{brown};

            \legend
            {
                $\sqrt{x}$,
                $x$,
                $x^2$,
                $x^3$
            }
        \end{loglogaxis}
    \end{tikzpicture}
\end{document}

Result:

Adriaan
  • 3,675
  • 2
  • 21
  • 41