Metapost 中的 arctime 如何工作?

Metapost 中的 arctime 如何工作?

请看以下Metapost代码:

path p;
p = (0,0){up}..{right}(200,100)..{up}(300,400)..cycle;
len := arclength p;
s := arctime (2500) of p;
t := arctime (len+2500) of p;
draw p;
show len;% 2799
show s;% 2.92...
show t;% 2.67...

为什么 s 和 t 不一样?我认为当我添加弧长时,什么都不会改变。错误在哪里?

编辑:我使用的是这里的 2.02 版本: http://www.tlhiv.org/mppreview/

This is MetaPost, version 2.02 (TeX Live 2023) (kpathsea version 6.3.5)  28 APR 2024 02:47
 **preview.mp
 (/usr/share/texlive/texmf-dist/metapost/base/mpost.mp
 (/usr/share/texlive/texmf-dist/metapost/base/plain.mp
 Preloading the plain mem file, version 1.005) ) (./preview.mp
 >> 2799.0210591829564
 >> 2.9211035593209118
 >> 2.6795082428530486 [0] )
 1 output file written: preview.mps

答案1

我并不声称完全理解它的arctime作用和计算它的算法。检查 MetaPost 源代码,在文件中mp.w(您可以尝试使用 cweave 将此 CWEB 文件编译为 PDF,但有些_s 没有前缀,\_这会导致 TeXed 时出错),第 405 节,“arclength 和 arctime 操作都基于递归函数,该函数根据 dz0、dz1、dz2... 找到三次样条的弧长”,实际实现是第mp_get_arc_time419 节中的函数。

通过阅读这些章节,我理解了是arctime通过查找零来实现的,使用浮点数(或定点数)的二进制搜索,来实现的反函数mp_do_arc_test()

如果在命令行中使用 MetaPost 并且默认为 32 位定点(又名缩放)epsilon = 0.00002,.

http://www.tlhiv.org/mppreview/使用 double,它设置epsilon = 1.52587890625e-05,并且其他数字系统都使用类似的值。

第 419 条规定,

如果 arc0 大于循环路径 h 的弧长,则结果是时间值大于路径的长度。

其中arc0是提供给 的数字参数arctime

使用问题中修改后的例子,

path p;
p = (0,0){up}..{right}(200,100)..{up}(300,400)..cycle;
len := arclength p;
s := arctime (2500) of p;
t := arctime (len+2500) of p;
show len;
show s;
show t;
show epsilon;
show arclength subpath (0,t) of p;
show len+2500;
end;

使用默认的比例数字系统:

>> 2799.02077
>> 2.92111
>> 5.92111
>> 0.00002
>> 5299.043
>> 5299.02077

使用-numbersystem=double

>> 2799.0210591829564
>> 2.9211035593209118
>> 2.6795082428530486
>> 1.52587890625e-05
>> 2200.7155501530865
>> 5299.0210591829564

在我看来,t=5.92是符合该描述的正确值,结果可以使用来解释t = s + l,其中l是循环路径的长度p,即长度为 3。此外,它符合 MetaPost 手册中关于行为的描述,arctime其中说arclength subpath (0,t) of p = a

因此,结果很可能是t=2.67...由于添加了不同的数字系统而导致的错误。

答案2

进一步更新:开发团队已将修复程序发布到存储库。我从那里提取了它并在本地构建了它,它看起来不错。使用下面粘贴的示例,我现在得到了这个:

> mpost b.mp
This is MetaPost, version 2.11 (TeX Live 2025/dev) (kpathsea version 6.4.0/dev)
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.02077
>> 2.92111
>> 5.92111
>> 3
>> "scaled" [1] )
1 output file written: b.1
Transcript written on b.log.

> mpost -numbersystem=double b.mp
This is MetaPost, version 2.11 (TeX Live 2025/dev) (kpathsea version 6.4.0/dev)
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.0210591829564
>> 2.9211035593209118
>> 5.9211035593209118
>> 3
>> "double" [1] )
1 output file written: b.1
Transcript written on b.log.

与其他数字系统类似。毫无疑问,此修复将在适当的时候进入标准发行版。

回答原始问题

MP 中的运算符返回路径达到 PostScript 点所期望长度所需的arctime时间。tarclength

因此,如果p是路径,并且a是所需长度,则arctime a of p给出时间t,使得arclength subpath(0, t) of p = a。在所有正常使用中,您应确保所需长度a介于 0 和 之间arclength p

但如果路径p恰好是循环的,那么您可以给出更长的长度。这类似于您可以参考等的方法。point 9 of fullcircle如果您检查源代码,您将看到 MP 专门规定所需长度比循环路径的实际长度更长。该算法沿着路径逐点工作,如果它回到循环的开头,它会进行计算以缩短其余过程(如果您真的想要详细信息,您可以检查源代码)。

实施此计算时,新数字系统出现了错误,现已更正。感谢开发团队的快速修复。


更新:开发团队确认这看起来像是由于 MP 源代码中使用了隐式整数数学而导致的一个错误。


这确实是一条评论,但是日志文件部分太长,所以我回答了这个问题。

使用当前版本的 MP,我发现您的示例使用旧scaled数字系统给出了预期结果。但使用三个新系统中的任何一个都会产生“意外”结果。这看起来需要向开发团队报告。

如果我在 OP 示例中添加几行,如下所示:

beginfig(1);
path p;
p = (0,0){up}..{right}(200,100)..{up}(300,400)..cycle;
len := arclength p;
s := arctime (2500) of p;
t := arctime (len+2500) of p;
draw p;
show len;% 2799
show s;% 2.92...
show t;% 2.67...
show arctime arclength p of p;
show numbersystem;

endfig;
end

mpost然后,如果我使用默认数字系统运行,我会得到这个日志文件:

This is MetaPost, version 2.10 (TeX Live 2024) (kpathsea version 6.4.0)  28 APR 2024 15:56
**b.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.02077
>> 2.92111
>> 5.92111
>> 3
>> "scaled" [1] )
1 output file written: b.1

但如果我使用其他三个数字系统中的任何一个,我都会得到“意外”的首次报告值。因此,显然在使用新数字系统t计算循环路径时出了问题。arclength

:!mpost -numbersystem=double b.mp
This is MetaPost, version 2.10 (TeX Live 2024) (kpathsea version 6.4.0)
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.0210591829564
>> 2.9211035593209118
>> 2.6795082428530486
>> 3
>> "double" [1] )
1 output file written: b.1
Transcript written on b.log.
"b.log" 12L, 389B    

:!mpost -numbersystem=decimal b.mp
This is MetaPost, version 2.10 (TeX Live 2024) (kpathsea version 6.4.0)  28 APR 2024 15:58
**b.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.021059182955437254465959453077
>> 2.921103559320912153438877894997069
>> 2.67950824285304864431956913069307
>> 3
>> "decimal" [1] )
1 output file written: b.1

:!mpost -numbersystem=binary b.mp
This is MetaPost, version 2.10 (TeX Live 2024) (kpathsea version 6.4.0)  28 APR 2024 15:58
**b.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/mpost.mp
(/usr/local/texlive/2024/texmf-dist/metapost/base/plain.mp
Preloading the plain mem file, version 1.005) ) (./b.mp
>> 2799.0210591829554372544659594531163
>> 2.9211035593209121534388778949970568
>> 2.6795082428530486443195691306930351
>> 3
>> "binary" [1] )
1 output file written: b.1

根据我使用 MP 的经验,旧scaled系统几乎总是更好。OP 可能想要求 thiv.org 预览器的所有者使用默认数字系统,除非另有特别要求。

相关内容