在“loglog”轴环境中使用“\pgfplotsextra”时轴限制错误?

在“loglog”轴环境中使用“\pgfplotsextra”时轴限制错误?

这是一个后续问题未明确设置时轴限制的键名称axis。那里给出的解决方案对于常规 PGFplots环境非常有效,但对于loglog轴环境则不然。\pgfkeysgetvalue{/pgfplots/...}{...}轴中的命令\pgfplotsextra似乎无法正常工作loglog。我该如何解决这个问题?

编译代码

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

\pgfplotsset{compat=newest}

\usetikzlibrary{calc}

\newcommand{\logLogSlopeTriangle}[9]
{
    % #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.
    % #6. xmin.
    % #7. xmax.
    % #8. ymin.
    % #9. ymax.

    \pgfplotsextra
    {
        % Calculate auxilliary quantities.
        \pgfmathsetmacro{\xA}{#6^(1-#1)*#7^#1}
        \pgfmathsetmacro{\yA}{#8^(1-#3)*#9^#3}
        \pgfmathsetmacro{\xB}{#6^(1-(#1-#2))*#7^(#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;
    }
}

\begin{document}
    \begin{tikzpicture}
        \begin{loglogaxis}
        [
            xmin=10^1, % WHAT IF I DON'T USE THIS?
            xmax=10^4, % WHAT IF I DON'T USE THIS?
            xlabel=$x$,
            ymin=10^0.5, % WHAT IF I DON'T USE THIS?
            ymax=10^4, % WHAT IF I DON'T USE THIS?
            ylabel style={rotate=-90},
            ylabel=$y$,
            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};

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

            \logLogSlopeTriangle{0.9}{0.1}{0.1}{1/2}{blue}{\xmin}{\xmax}{\ymin}{\ymax};
            \logLogSlopeTriangle{0.75}{0.1}{0.1}{1}{red}{\xmin}{\xmax}{\ymin}{\ymax};

        \end{loglogaxis}
    \end{tikzpicture}
\end{document}

我得到了想要的结果

如果我不想在轴选项中明确指定轴限制,请\pgfplotsextra使用未明确设置时轴限制的键名称应该提供一个解决方案。

因此编译代码

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

\pgfplotsset{compat=newest}

\usetikzlibrary{calc}

\newcommand{\logLogSlopeTriangle}[9]
{
    % #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.
    % #6. xmin.
    % #7. xmax.
    % #8. ymin.
    % #9. ymax.

    \pgfplotsextra
    {
        % Calculate auxilliary quantities.
        \pgfmathsetmacro{\xA}{#6^(1-#1)*#7^#1}
        \pgfmathsetmacro{\yA}{#8^(1-#3)*#9^#3}
        \pgfmathsetmacro{\xB}{#6^(1-(#1-#2))*#7^(#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;
    }
}

\begin{document}
    \begin{tikzpicture}
        \begin{loglogaxis}
        [
            %xmin=10^1, % WHAT IF I DON'T USE THIS?
            %xmax=10^4, % WHAT IF I DON'T USE THIS?
            xlabel=$x$,
            %ymin=10^0.5, % WHAT IF I DON'T USE THIS?
            %ymax=10^4, % WHAT IF I DON'T USE THIS?
            ylabel style={rotate=-90},
            ylabel=$y$,
            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};

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

            \logLogSlopeTriangle{0.9}{0.1}{0.1}{1/2}{blue}{\xmin}{\xmax}{\ymin}{\ymax};
            \logLogSlopeTriangle{0.75}{0.1}{0.1}{1}{red}{\xmin}{\xmax}{\ymin}{\ymax};

        \end{loglogaxis}
    \end{tikzpicture}
\end{document}

结果是

。如您所见,三角形的位置不对。我该如何修复?

答案1

这与其说是一个解决方案,不如说是一个演示。右下角是没有使用 \pgfplotsextra 计算的 (\xmin,\xmax,\ymin,\ymax),右上角是使用 \pgfplotsextra 计算的。使用计算器可以显示 e^\xmin=5 和 e^\xmax=20,000,它们对应于轴限值。

演示

\documentclass{standalone}
\usepackage{pgfplots}
\begin{document}
    \begin{tikzpicture}
        \begin{loglogaxis}
        [
            %xmin=10^1, % WHAT IF I DON'T USE THIS?
            %xmax=10^4, % WHAT IF I DON'T USE THIS?
            xlabel=$x$,
            %ymin=10^0.5, % WHAT IF I DON'T USE THIS?
            %ymax=10^4, % WHAT IF I DON'T USE THIS?
            ylabel style={rotate=-90},
            ylabel=$y$,
            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};

            \pgfkeysgetvalue{/pgfplots/xmin}{\xmin}
            \pgfkeysgetvalue{/pgfplots/xmax}{\xmax}
            \pgfkeysgetvalue{/pgfplots/ymin}{\ymin}
            \pgfkeysgetvalue{/pgfplots/ymax}{\ymax}
            \node[above left] at (rel axis cs: 1,0) {(\xmin, \xmax, \ymin, \ymax)};

            \pgfplotsextra
            {
                \pgfkeysgetvalue{/pgfplots/xmin}{\xmin}
                \pgfkeysgetvalue{/pgfplots/xmax}{\xmax}
                \pgfkeysgetvalue{/pgfplots/ymin}{\ymin}
                \pgfkeysgetvalue{/pgfplots/ymax}{\ymax}
                \node[below left] at (rel axis cs: 1,1) {(\xmin, \xmax, \ymin, \ymax)};
            }

        \end{loglogaxis}

    \end{tikzpicture}
\end{document}

答案2

正确的代码似乎是

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

\pgfplotsset{compat=newest}

\usetikzlibrary{calc}

\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;
    }
}

\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};

            \logLogSlopeTriangle{0.9}{0.1}{0.1}{0.5}{blue};
            \logLogSlopeTriangle{0.75}{0.1}{0.1}{1}{red};
        \end{loglogaxis}
    \end{tikzpicture}
\end{document}

,其中我将其替换\xmin(exp(\xmin))、、、和。\xmax(exp(\xmax))\ymin(exp(\ymin))\ymax(exp(\ymax))

显然,使用\pgfplotsextra给出了轴限制,log(...)因此exp(...)需要应用它来获得正确的局部坐标。

结果如下:

答案3

\pgfplotsextra大致是pgfplotsTikZ/PGF 等效的命令\pgfextra

这里有两件事相互作用。首先,在路径绘制执行方面,pgfplotsTikZ 不是,这是有充分理由的。因为它必须基于绘制的实体创建一个轴,以便路径被轴限制紧密封装,刻度、网格线和刻度标签会自动计算等等。为了做到这一点,pgfplots 会收集所有可能绘制的东西,直到轴环境完成。

然后开始评估最大值、极限等,并准备轴,然后才开始将收集的项目作为绘图命令传输到 PGF。所以最后你看到的是一堆在 TikZ 图片中绘制的 PGF 路径。

然而,TikZ 没有这种行为。当您发出路径命令时,它会立即发送相关的驱动程序命令,并命令 PDF 特殊命令。如果\pgfextra需要推迟当前路径构建,请执行参数\pgfextra(例如更改某些定义或执行和定义某些计算),然后恢复路径构建。

如果pgfplots需要将原生 TikZ 绘图命令与 pgfplots 的绘图对象一起传输,以便在轴集合完成后也执行它们。例如,在轴完成之前未设置 值,并且您可能会读取默认值(如果不是零)xminxmax

本质上这就是为什么需要使用\pgfplotsextra其他方法,因为您已经体验过所有数字和维度等都未启动,但解析仍然完成,pgfplots因此您会得到奇怪形状的路径(我认为这里它们都是 log()版本而不是实际单位但没有检查)。

需要注意的是,当遇到 TikZ 路径命令时pgfplots,它通常足够聪明,可以自动执行\pgfplotsextra添加。但如果需要在轴完成后计算额外的数据,它就无法提供进一步的帮助。

对于您来说,有更简单的替代方案:

  1. 如果绘图大部分是线性的,则将坐标放在绘图上并执行所需的任何操作

  2. 如果您有复杂的情节,需要切线和其他复杂因素,请使用装饰。

对于第一种情况举例:

\documentclass[margin=1cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}
\begin{document}
  \begin{tikzpicture}
    \begin{loglogaxis}[
    xlabel=$x$,
    ylabel style={rotate=-90},
    ylabel=$y$,
    grid=major,
    ]
      \addplot[blue,line width=1pt,domain=10^1:10^4] {sqrt(x)} 
         coordinate[pos=0.50] (a) 
         coordinate[pos=0.75] (b);
      \draw[blue] (a) -| (b) 
         node[pos=0.25,below] {1} 
         node[pos=0.75,right] {2}; % Or whatever complicated label

    \end{loglogaxis}
  \end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容