![在轴环境中扩展 \pgfplotsinvokeforeach 中的宏](https://linux22.com/image/361513/%E5%9C%A8%E8%BD%B4%E7%8E%AF%E5%A2%83%E4%B8%AD%E6%89%A9%E5%B1%95%20%5Cpgfplotsinvokeforeach%20%E4%B8%AD%E7%9A%84%E5%AE%8F.png)
我使用 \pgfplotsinvokeforeach 和 \pgfplotstablegetelem 从表中提取某些数据值,然后将其直接绘制到 pgfplots 轴上。从表中任何一行提取的数据用于在与时间 (m) 和高度 (h_Moon) 对应的坐标处绘制月相。
我的 MWE 如下。就目前情况而言,我认为存在与宏评估被推迟相关的问题。(例如参见此处)。编译结果只使用循环中的最后一项。我无法让循环使用表中的所有行,为每个行绘制一个月相。
\begin{filecontents*}{Tracking.txt}
m A_Moon h_Moon k_Moon i_Moon chi_Moon
1 45.5814 -17.1705 0.0569126 152.396 110.821
2 58.0011 -9.82216 0.0547727 152.93 111.058
3 69.4323 -1.41611 0.052673 153.464 111.299
4 80.3212 7.64628 0.0506139 153.997 111.542
5 91.1983 17.0132 0.0485953 154.53 111.789
6 102.694 26.336 0.0466174 155.062 112.041
7 115.596 35.2012 0.0446804 155.594 112.296
\end{filecontents*}
\documentclass[]{article}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
xlabel={Time (hr)},
ylabel={Altitude ($^\circ$)},
xmin=0,
xmax=12,
ymin=-90,
ymax=90,
xtick={0,1,...,12},
ytick={-80,-60,...,80}
]
\pgfplotstableread{Tracking.txt}\Tracking;
\newlength{\moonsize}\setlength{\moonsize}{10pt}
\pgfplotsinvokeforeach {1,2,...,6} {
\pgfplotstablegetelem{#1}{m}\of{\Tracking}\pgfmathsetmacro{\MoonFigurePointX}{\pgfplotsretval}
\pgfplotstablegetelem{#1}{h_Moon}\of{\Tracking}\pgfmathsetmacro{\MoonFigurePointY}{\pgfplotsretval}
\pgfplotstablegetelem{#1}{k_Moon}\of{\Tracking}\pgfmathsetmacro{\MoonFigureFraction}{\pgfplotsretval}
\pgfplotstablegetelem{#1}{i_Moon}\of{\Tracking}\pgfmathsetmacro{\MoonFigurePhase}{\pgfplotsretval}
\pgfplotstablegetelem{#1}{chi_Moon}\of{\Tracking}\pgfmathsetmacro{\MoonFigureAngle}{\pgfplotsretval}
\begin{scope}[rotate around={\MoonFigureAngle+90:(axis cs:\MoonFigurePointX,\MoonFigurePointY)}]
\pgfmathparse{(\MoonFigurePhase>=0)?1:0}\ifdim\pgfmathresult pt>0pt%
\draw [fill=black!10] ++(axis cs:\MoonFigurePointX,\MoonFigurePointY) ++(0,-\moonsize) arc [start angle=-90,end angle=90,radius=\moonsize] arc [start angle=90,end angle=270,y radius=\moonsize,x radius={-\moonsize + \MoonFigureFraction*2*\moonsize}];
\fi
\pgfmathparse{(\MoonFigurePhase<0)?1:0}\ifdim\pgfmathresult pt>0pt%
\draw [fill=black!10] ++(axis cs:\MoonFigurePointX,\MoonFigurePointY) ++(0,-\moonsize) arc [start angle=90,end angle=-90,radius=-\moonsize] arc [start angle=90,end angle=270,y radius=\moonsize,x radius={\moonsize - \MoonFigureFraction*2*\moonsize}];
\fi
\end{scope}
\draw (axis cs:\MoonFigurePointX,\MoonFigurePointY) node [font=\scriptsize,below=0.7\moonsize] {\pgfmathparse{int(round(\MoonFigureFraction*1000))/10}\pgfmathprintnumber{\pgfmathresult}\%};
}
\end{axis}
\end{tikzpicture}
\end{document}
代码产生如下结果:
然而,我想要得到这个:
在上面的链接中,建议的解决方法是使用 \edef 显式扩展循环变量。我尝试过这种方法以及许多不同的方法,但它仍然只使用表中的最后一行。
此外,我并不完全相信宏扩展就是全部问题。例如,如果我将消息 (\MoonFigurePointX) 插入到循环中,我可以在日志中看到在循环的每次迭代中确实从表中读取了正确的值。
请注意,这只是一个更大问题的一个方面。还有其他事情没有出现在这个 MWE 中(并且不会直接影响我遇到的问题),这解释了为什么我直接在 pgfplots 轴上绘图,而从 MWE 来看,似乎没有理由使用轴。
最后,这是我的第一篇 tex.stackexchange 帖子(我通常可以通过 Google 和耐心解决 LaTeX 问题,但这次不行)。如果我没有正确遵守规则,或者您认为我可以改进我的问题,请告诉我,我会做出调整。
答案1
我设法找到了一个解决方案。我认为它不是很优雅,但它有效。
正如我猜测的那样,问题在于 (1) 宏扩展被推迟到循环完成后,以及 (2) 我对宏扩展的理解不够深入。
我已将月亮绘制代码移入,并找到了和与变量\newcommand\drawmoon[5]
的有效组合,以包含扩展的宏。我还将循环中的使用替换为。\edef
\noexpand
\tmp
\pgfmathsetmacro
\edef
更新后的 MWE 如下:
\begin{filecontents*}{Tracking.txt}
m A_Moon h_Moon k_Moon i_Moon chi_Moon
1 45.5814 -17.1705 0.0569126 152.396 110.821
2 58.0011 -9.82216 0.0547727 152.93 111.058
3 69.4323 -1.41611 0.052673 153.464 111.299
4 80.3212 7.64628 0.0506139 153.997 111.542
5 91.1983 17.0132 0.0485953 154.53 111.789
6 102.694 26.336 0.0466174 155.062 112.041
7 115.596 35.2012 0.0446804 155.594 112.296
\end{filecontents*}
\documentclass[]{article}
\usepackage{pgfplots}
\newlength{\moonsize}\setlength{\moonsize}{10pt}
\newcommand\drawmoon[5]{
\edef\tmp{\noexpand\begin{scope}[rotate around={#5+90:(axis cs:#1,#2)}]}\tmp
\pgfmathparse{(#4>=0)?1:0}\ifdim\pgfmathresult pt>0pt%
\edef\tmp{\noexpand\draw [fill=black!10] ++(axis cs:#1,#2) ++(0,-\moonsize) arc [start angle=-90,end angle=90,radius=\moonsize] arc [start angle=90,end angle=270,y radius=\moonsize,x radius={-\moonsize + #3*2*\moonsize}];}\tmp
\fi
\pgfmathparse{(#4<0)?1:0}\ifdim\pgfmathresult pt>0pt%
\edef\tmp{\noexpand\draw [fill=black!10] ++(axis cs:#1,#2) ++(0,-\moonsize) arc [start angle=90,end angle=-90,radius=-\moonsize] arc [start angle=90,end angle=270,y radius=\moonsize,x radius={\moonsize - #3*2*\moonsize}];}\tmp
\fi
\end{scope}
\edef\tmp{\noexpand\draw (axis cs:#1,#2) node [font=\noexpand\scriptsize,below=0.7\moonsize] {\noexpand\pgfmathparse{int(round(#3*1000))/10}\noexpand\pgfmathprintnumber{\noexpand\pgfmathresult}\%};}\tmp
}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
xlabel={Time (hr)},
ylabel={Altitude ($^\circ$)},
xmin=0,
xmax=12,
ymin=-90,
ymax=90,
xtick={0,1,...,12},
ytick={-80,-60,...,80}
]
\pgfplotstableread{Tracking.txt}\Tracking;
\pgfplotsinvokeforeach {1,2,...,6} {
\pgfplotstablegetelem{#1}{m}\of{\Tracking}\edef\MoonFigurePointX{\pgfplotsretval}
\pgfplotstablegetelem{#1}{h_Moon}\of{\Tracking}\edef\MoonFigurePointY{\pgfplotsretval}
\pgfplotstablegetelem{#1}{k_Moon}\of{\Tracking}\edef\MoonFigureFraction{\pgfplotsretval}
\pgfplotstablegetelem{#1}{i_Moon}\of{\Tracking}\edef\MoonFigurePhase{\pgfplotsretval}
\pgfplotstablegetelem{#1}{chi_Moon}\of{\Tracking}\edef\MoonFigureAngle{\pgfplotsretval}
\drawmoon{\MoonFigurePointX}{\MoonFigurePointY}{\MoonFigureFraction}{\MoonFigurePhase}{\MoonFigureAngle}
}
\end{axis}
\end{tikzpicture}
\end{document}