请看以下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_time
419 节中的函数。
通过阅读这些章节,我理解了是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
时间。t
arclength
因此,如果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 预览器的所有者使用默认数字系统,除非另有特别要求。