宏构建坐标中断 pgfplot 中的 \addplot 命令

宏构建坐标中断 pgfplot 中的 \addplot 命令

我想使用类似以下的方法创建在文档顶部定义的一些数据点的图: \newcommand{\test}{{3,4,2,5}}

为了做到这一点,我创建了一个宏来解析这些值并将它们转换成类似的东西:

(0,3) (1,4) (2,2) (3,5)

不幸的是,如果我使用宏来生成它,我会得到 Incomplete \ifx; all text was ignored after line 33. 第 33 行要求 pgfplot 将坐标添加到图形中(参见下面的完整文件)。

另一方面,如果我直接创建坐标:

\newcommand{\tester}{ { (1.0,3)  (2.0,4)  (3.0,2)  (4.0,5) } }
...
\addplot coordinates { {\tester} };

一切进展顺利。另一方面,如果我使用宏:

\newcommand{\tester}{ \makeCoords{\test} }
...
\addplot coordinates { {\tester} };

然后我得到了编译错误。请注意,\tester创建坐标时我可以打印出来,一切看起来都很好。

下面是示例测试代码。通过切换第 18 行和第 19 行的注释,您可以在查看程序是否正常运行和是否出现问题之间来回切换。有什么想法可以解决这个问题吗?

\documentclass{article}
\usepackage{pgfplots}

\begin{document}
\newcommand{\test}{{3,4,2,5}}

\newcommand{\pgfval}[1]{\pgfmathparse{#1}\pgfmathresult}

\newcommand{\makeCoords}[2][0]{\foreach \tmp in #2{
    \foreach \testVal[count=\i] in \tmp{
        (\pgfval{\i+#1},\testVal)
    }
}%foreach
}%newcommand

Test is \test

\newcommand{\tester}{\makeCoords{\test}}
% \newcommand{\tester}{ { (1.0,3)  (2.0,4)  (3.0,2)  (4.0,5) } }

tester is \tester  % Print out for debugging

\begin{figure}
\begin{tikzpicture}
    \begin{axis}[
        xlabel={timestep},
        ylabel={Location(x)},
        xmin=0, xmax=6,
        ymajorgrids=true,
        grid style = dashed
    ]    
    
    \addplot coordinates { {\tester} };
    \end{axis}
\end{tikzpicture}
\end{figure}
\end{document}

答案1

使用表格可能pgfplotstable会有效。从这样的表格中绘制列并计算x expr绘图的 x 值当然很简单。请参见下面的示例。

可以使用 访问表中的各个值\pgfplotstablegetelem{<row>}{<column>}\of\tablename,并将结果保存在 中\pgfplotsretval

在此处输入图片描述

\documentclass{article}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.18}
\begin{document}
\pgfplotstableread{
3
4
2
5
}\test

You can print the table:

% the option hides the header row
\pgfplotstabletypeset[every head row/.style={output empty row}]\test


% indexing in tables starts at zero, so this is the third row, first column
\pgfplotstablegetelem{2}{[index]0}\of\test
\pgfmathsetmacro\foo{\pgfplotsretval}

Now the third element in the table is \foo.

\begin{tikzpicture}
    \begin{axis}[
        xlabel={timestep},
        ylabel={Location(x)},
        xmin=0, xmax=6,
        ymajorgrids=true,
        grid style = dashed
    ]    
    
    \addplot table[x expr=\coordindex+1,y index=0] {\test};
    \end{axis}
\end{tikzpicture}
\end{document}

答案2

作为练习,这里有一个解决方案functional包裹:

\documentclass{article}

\usepackage{pgfplots}
\usepackage{functional}

\begin{document}

\newcommand{\test}{3,4,2,5}

\IgnoreSpacesOn
\PrgNewFunction \MakeCoords {M} {
  \ClistClear \lTmpaClist
  \IntZero \lTmpaInt
  \ClistVarMapInline #1 {
    \IntIncr \lTmpaInt
    \ClistPutRight \lTmpaClist {\Expand{{(\OnlyValue\lTmpaInt,##1)}}}
  }
  \TlSet #1 {\ClistVarJoin \lTmpaClist {~}}
}
\IgnoreSpacesOff

Test is \test

\MakeCoords \test

Test is \test

\begin{figure}
\begin{tikzpicture}
  \begin{axis}[
    xlabel={timestep},
    ylabel={Location(x)},
    xmin=0, xmax=6,
    ymajorgrids=true,
    grid style = dashed
  ]    
  \addplot coordinates { {\test} };
  \end{axis}
\end{tikzpicture}
\end{figure}

\end{document}

在此处输入图片描述

答案3

您可以使用\foreach-loop 来收集临时宏中的内容。循环完成后,使用临时宏执行临时宏扩展的任何操作。例如,操作可以是定义\tester保存坐标的宏的命令。

\DefineCoordsMacro[⟨x-shift of coordinates⟩]%
                  {⟨definition-command for defining macro holding list of coordinates⟩}%
                  {⟨braced comma-list or macro holding unbraced comma-list of y-values of coordinates⟩}
\documentclass{article}
\usepackage{pgfplots}

\newcommand\Scratchmacro{}
\newcommand\Exchange[2]{#2#1}
\makeatletter
\newcommand{\DefineCoordsMacro}[3][0]{%
  \begingroup
  \gdef\Scratchmacro{ }%
  \foreach \testVal[count=\i] in #3{%
    \pgfmathparse{\i+#1}%
    \xdef\Scratchmacro{%
      \unexpanded\expandafter{\Scratchmacro}%
      (%
      \unexpanded\expandafter{\pgfmathresult}%
      ,%
      \unexpanded\expandafter{\testVal}%
      ) %
    }%
  }%foreach
  \expandafter\Exchange\expandafter{\expandafter{\Scratchmacro}}{\endgroup#2}%
}%newcommand
\makeatother


\begin{document}

\newcommand{\test}{3,4,2,5}
\DefineCoordsMacro{\newcommand\tester}{\test}
%\DefineCoordsMacro[2]{\renewcommand\tester}{{3,4,2,5}}

% Print out for debugging:
\noindent
The meaning of the macro \texttt{\string\test} is:\\ \texttt{\meaning\test}

\noindent
The meaning of the macro \texttt{\string\tester} is:\\ \texttt{\meaning\tester}

\begin{figure}
\noindent
\begin{tikzpicture}
    \begin{axis}[
        xlabel={timestep},
        ylabel={Location(x)},
        xmin=0, xmax=6,
        ymajorgrids=true,
        grid style = dashed
    ]    
    
    \addplot coordinates { {\tester} };
    \end{axis}
\end{tikzpicture}
\end{figure}
\end{document}

在此处输入图片描述

相关内容