metapost 中 for 循环中的标签编号

metapost 中 for 循环中的标签编号

我首先在 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为接受两个参数

  1. string或表达式picture(仅此而已)
  2. 表达式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。这是因为btexetex就像一对特殊的引号,将标记列表转换为变量,但 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 ...

然后将它们全部读回并一次性处理。

现代、快速的动态标签

但实际上你不再需要做这些了。相反,你应该使用 lualatexluamplib来代替。使用这样的模板,并使用 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,它将增加您获得任何答案的机会,因为我们不需要做任何额外的工作。

相关内容