Пожалуйста, посмотрите на следующий код 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
(вы можете попробовать скомпилировать этот файл CWEB в PDF с помощью cweave, но некоторые _
s не имеют префикса, \_
что приводит к ошибке при TeXed), раздел 405, «Операции arclength и arctime основаны на рекурсивной функции, которая находит длину дуги кубического сплайна по заданным dz0, dz1, dz2...», а фактическая реализация — это функция mp_get_arc_time
в разделе 419.
Прочитав эти разделы, я понял, что это arctime
реализуется путем нахождения нуля с использованием двоичного поиска по числам с плавающей точкой (или с фиксированной точкой) для реализации обратной функции mp_do_arc_test()
.
При использовании MetaPost в командной строке с 32-битной фиксированной точкой по умолчанию (т. е. масштабированной), epsilon = 0.00002
.
Thehttp://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 Manual о поведении, в 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.
и аналогично из других числовых систем. Это исправление, несомненно, войдет в стандартные дистрибутивы в свое время.
Отвечая на первоначальный вопрос
Оператор arctime
в MP возвращает время t
на пути, когда arclength
путь достигает желаемой длины в пунктах PostScript.
Итак, если 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
first reported. Так что, по-видимому, что-то идет не так при вычислении 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 использовать систему нумерации по умолчанию, если иное не оговорено особо.