我首先在 MetaPost 中创建十个点 p[1],..., p[10]。然后,我使用以下循环:
for i = 1 upto 10:
dotlabel.bot(btex i etex, p[i]);
endfor
然后它会在 pdf 文件中创建 10 个字母 'i',位于 10 个点 p[i] 下方。但我想要 10 个点 p[i] 下方的 10 个数字,从 1 到 10。
我不知道该怎么做。请帮帮我。
答案1
关于 Metapost 中的动态标签
在 中,宏label
被定义plain.mp
为接受两个参数
string
或表达式picture
(仅此而已)- 表达式
pair
它会将字符串或图片整齐地绘制在由对表达式定义的点上。所以你可以这样做
label("Hello", origin);
使“Hello” 居中(0, 0)
。
其工作方式如下(简化):
vardef label(expr s,z) =
save p; picture p;
p = s if string s: infont defaultfont fi;
... positioning code ...
enddef;
因此,如果第一个参数s
是字符串,那么宏会p
首先将其转换为图片。
那么问题是,如何循环动态地生成字符串或图片?
默认字体的简单标签
将数字变量转换为字符串的最简单方法是使用decimal
for i = 1 upto 10:
label(decimal i, (20i, 0));
endfor
或者您可能想使用默认字体以外的特定字体。
for i = 1 upto 10:
label(decimal i infont "phvr8r", (20i, 0));
endfor
picture
现在您每次都会发送一个标签。
使用 TeX 的动态标签
您无法直接使用 生成动态标签btex ... etex
。这是因为btex
和etex
就像一对特殊的引号,将标记列表转换为变量,但 MP在使用 TeX 处理它们之前picture
不会扩展其中的任何标记。所以如果你尝试这样做btex ... etex
for i = 1 upto 10:
label(btex i etex, (20i, 0));
endfor
您没有收到任何错误,但每个标签都是一个“i”。要解决这个问题,您可以使用宏TEX
。
input TEX
for i = 1 upto 10:
label(TEX(decimal i), (20i, 0));
endfor
该TEX
宏接受一个正则string
并将其传递给 TeX,然后返回结果picture
。这意味着你可以做类似的事情
input TEX
for i = 1 upto 10:
label(TEX("$p_{" & decimal i & "}$"), (20i, 0));
endfor
因为 MP 会在将标记传递给宏之前对其进行扩展TEX
。在本例中,有三个字符串需要连接。
使用 TeX 更快地实现动态标签
TEX 宏的唯一问题是它非常慢。因为它将每个标签写入临时文件。以一些低级操作为代价,write
你可以像这样加快它的速度。
for i = 1 upto 10:
write "label(btex $p_{" & decimal i & "}$ etex, (" & decimal 20i & ",0));" to ".mplabels";
endfor
write EOF to ".mplabels";
input ".mplabels";
这会将十行内容写入临时本地文件:
label(btex $p_{1}$ etex, (20, 0));
label(btex $p_{2}$ etex, (40, 0));
label(btex $p_{3}$ etex, (60, 0));
... etc ...
然后将它们全部读回并一次性处理。
现代、快速的动态标签
但实际上你不再需要做这些了。相反,你应该使用
lualatex
和luamplib
来代替。使用这样的模板,并使用
lualatex
而不是 来处理它mpost
。
\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable} % <--- this is important
\begin{mplibcode}
beginfig(1);
endfig;
\end{mplibcode}
\end{document}
然后你可以像这样高速制作动态标签
\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);
for i = 1 upto 10:
label("$p_{" & decimal i & "}$", (20i, 0));
endfor
endfig;
\end{mplibcode}
\end{document}
生成如下内容(使用 编译时lualatex
)
答案2
您的错误与使用有关btex etex
。此答案有效:
\starttext
\startMPpage
path p[];
for i = 1 upto 10:
p[i]:= (10i,0);
dotlabel.bot(i, p[i]);
endfor
%variables
\stopMPpage
\stoptext
顺便说一句,请给我们一个完全可编译的 MWE,它将增加您获得任何答案的机会,因为我们不需要做任何额外的工作。