刷新 PGF 命令和局部变量

刷新 PGF 命令和局部变量

我认为我需要一种方法来刷新 PGF 命令,因为引用\LabelText使用最后一个值,而不是调用时的值。该宏旨LabelPoint在替换所示的第一个\addplot命令,并使用坐标或指定的标签(如果给出)标记该点。但是,两个点都被标记为top

\documentclass{article}
\usepackage{pgfplots}
\usepackage{xparse}

\begin{document}
\newcommand{\LabelText}{}
\NewDocumentCommand{\LabelPoint}{o o m m g}{
    \IfNoValueTF{#5}{
        \renewcommand{\LabelText}{$(#3,#4)$} % Label with given coordinates
    }{
        \renewcommand{\LabelText}{#5} % Use given label
    }
    \addplot [#1] coordinates{(#3,#4)} node [#2] {\LabelText};

    %\pgfsyssoftpath@flushcurrentpath % -- Syntax error
    %\pgfusepath{fill}                % -- no effect
}

\NewDocumentCommand{\LabelPointX}{o o m m g}{
  \IfNoValueTF{#5}{
    \addplot [#1] coordinates{(#3,#4)} node [#2] {$(#3,#4)$};
  }{
    \addplot [#1] coordinates{(#3,#4)} node [#2] {#5};
  }
}

\begin{tikzpicture}
\begin{axis}
    \addplot [mark=*,color=red] coordinates{(0,0)} node [color=blue, below] {$(0,0)$};
    \LabelPoint[mark=*,color=red][color=blue, below]{0.5}{0.5}{middle}
    \LabelPoint[mark=*,color=red][color=blue, below]{1  }{1  }{top}
\end{axis}
\end{tikzpicture}
\end{document}

我认为问题与 PGF 命令未被刷新有关,但我似乎无法让它工作——我已注释掉我尝试过的内容。

我也不喜欢拥有全局变量\LabelText,因为它只在宏范围内才有意义,所以任何将其移动到范围内的帮助\NewDocumentCommand也会有所帮助。

\LabelTextX使用两个不同命令的修改版本\addplot可以工作,但这只会使代码更难阅读,并且在涉及更多条件时变得复杂,所以我真的不想使用它作为解决方案。

答案1

如果我理解正确的话,\LabelPointX它会按照你的要求执行,并\LabelPoint执行相同的操作。你想要重构,\LabelPoint这样重复性就会降低。

您喜欢这个实现吗?

\NewDocumentCommand{\LabelPointY}{o o m m g}{
  \addplot [#1] coordinates{(#3,#4)} node [#2] {\IfNoValueTF{#5}{$(#3,#4)$}{#5}};
}

这不需要任何临时变量,也不会重复任何内容。

答案2

这是一个扩展问题。标签文本按原样传递给路径生成器,并在不扩展的情况下存储。它仅在构建路径时扩展,由于您在单个路径上执行了几次此操作,因此标签文本都扩展为相同的内容。您可以通过将宏的内容括\LabelPoint在 TeX 分组级别中(例如,通过将左括号和右括号加倍)来看到这种情况。这会导致更改\LabelText仅限于定义,并且在构建路径时,它使用全局版本(恰好为空)。

因此,解决方案是以预扩展的方式将标签文本宏传递给路径。如果推广,这可能会有点问题,而且有很多解决方案。至于哪个最好,我没有资格评判!这里有一种方法,它使用辅助宏和单个\expandafter

\documentclass{article}
\usepackage{pgfplots}
\usepackage{xparse}

\begin{document}
\newcommand{\LabelText}{}
\NewDocumentCommand{\LabelPoint}{o o m m g}{
  \def\plotcmd{\addplot [#1] coordinates{(#3,#4)} node [#2]}
    \IfNoValueTF{#5}{
        \renewcommand{\LabelText}{ {$(#3,#4)$}} % Label with given coordinates
    }{
        \renewcommand{\LabelText}{ {#5}} % Use given label
    }

  \expandafter\plotcmd\LabelText;

    %\pgfsyssoftpath@flushcurrentpath % -- Syntax error
    %\pgfusepath{fill}                % -- no effect
}

\NewDocumentCommand{\LabelPointX}{o o m m g}{
  \IfNoValueTF{#5}{
    \addplot [#1] coordinates{(#3,#4)} node [#2] {$(#3,#4)$};
  }{
    \addplot [#1] coordinates{(#3,#4)} node [#2] {#5};
  }
}

\begin{tikzpicture}
\begin{axis}
    \addplot [mark=*,color=red] coordinates{(0,0)} node [color=blue, below] {$(0,0)$};
    \LabelPoint[mark=*,color=red][color=blue, below]{0.5}{0.5}{middle}
    \LabelPoint[mark=*,color=red][color=blue, below]{1  }{1  }{top}
\end{axis}
\end{tikzpicture}
\end{document}

请注意,我们在宏中加入了括号\LabelText。这只会让组装最终命令变得更容易一些。使用辅助\plotcmd宏只会节省很多s \expandafter。整个目的是\LabelText应该在命令处理之前进行扩展\addplot,以便价值看到的是of \LabelText,而不是\LabelText它本身。因此,TeX 愉快地解析了这一行,看到了,\expandafter所以\LabelText首先扩展。然后跳回扩展\plotcmd,扩展到\addplot ...内容。然后它再次从开始,\addplot但现在,由于我们的扩展魔法,输入流由以下部分组成:

\addplot [#1] coordinates {(#3,#4)} node [#2] {label};

这正是我们想要的:

在此处输入图片描述

相关内容