MetaPost
MetaPost — интерпретатор языка программирования META, который можно использовать для создания графических иллюстраций. MetaPost был создан Джоном Хобби в то время, когда он был аспирантом у Дональда Э. Кнута. В качестве основы была взята система создания шрифтов METAFONT.
На входе интерпретатору подаётся текст на META, а на выходе получается графический файл в формате PostScript. Язык META, унаследованный от METAFONT, позволяет оперировать геометрическими объектами, такими как: точка, путь, картинка и выполнять над ними различные алгебраические действия, например, сдвиг, вращение и другие линейные преобразования.
Основными отличиями MetaPost от METAFONT кроме выходного формата является наличие поддержки цвета и возможность делать текстовые вставки. Текстовые вставки создаются с помощью LaTeX, таким образом, любая конструкция, которая может быть создана в LaTeX, также может быть вставлена в картинку MetaPost.
Интерпретатор MetaPost (исполняемый файл mpost) вместе со стандартными макро-библиотеками распространяется как открытое программное обеспечение, обычно, в составе дистрибутивов LaTeX.
MetaPost-конвейерПравить
На вход программы mpost подаётся «META-картинка». «META-картинка» — это текстовый файл с расширением .mp (далее для краткости mp-файл) с инструкциями на языке META. В одном mp-файле можно хранить несколько описаний картинок. При компиляции с помощью mpost создаются файлы с тем же именем, что и у исходного файла, но с расширениями в виде чисел, которые указываются в декларации beginfig. Результирующие файлы сразу можно вставлять в LaTeX-тексты с помощью обычного \includegraphics. Для этого достаточно в заголовок tex-файла добавить команду из LaTeX-пакета graphicx:
\DeclareGraphicsRule{*}{eps}{*}{}
От «правильных» eps-файлов они отличаются только тем, что в них не «внедрены» шрифты, поэтому просмотреть их без дополнительной обработки не удастся.
Шрифты можно внедрить посредством программ latex и dvips с результатом в виде eps-файла или скрипта mptopdf с результатом в виде pdf-файла. Эти картинки уже можно использовать независимо любой программой, которая поддерживает эти векторные форматы.
Кириллица и MetaPostПравить
Внедрить кириллицу в метки MetaPost можно только с помощью LaTeX. Для этого mp-файл должен иметь примерно следующий заголовок:
verbatimtex \documentclass[12pt]{minimal} %простейшая кириллизация \usepackage[koi8-r]{inputenc} \usepackage[english,russian]{babel} \begin{document} etex;
Этот заголовок будет использоваться каждый раз, когда MetaPost доходит до текста, находящегося между метками btex и etex. Если для создание метки требуется какой-либо пакет LaTeX, то, соответственно, необходимо добавить этот пакет в заголовок стандартным образом.
Для того, чтобы при создании надписи использовался именно latex, интерпретатор mpost должен запускаться с опцией -tex=latex. Если эта опция отсутствует, то информацию о том, что следует запускать, mpost ищет в переменной окружения TEX. По умолчанию вместо latex запускается tex.
Если в тексте определяется переменная prologues, то она должна быть равна 0. В этом случае все необходимые шрифты «подшиваются» к картинке в момент, когда создаются eps и pdf-файлы.
Структура mp-файлаПравить
После заголовка идут описания картинок. Каждая картинка заключается между командами beginfig и endfig. В качестве параметра beginfig указывается порядковый номер картинки. При компиляции этот номер будет добавляться к картинке как расширение. Пример:
%Математический HelloWorld beginfig(3) ; for alpha:=90 step -9 until 0: label(btex \(f(x)= \frac{1}{\sqrt{2\pi}\,\sigma} \int\limits_{-\infty}^{\infty} e^{-\frac{x^2}{2\sigma^2}}dx\) etex scaled (5*(1-alpha/100)) rotated alpha,(0,0)) withcolor (max(1-alpha/45,0)*red+min(alpha/45,2-alpha/45)*green+ max(alpha/45-1,0)*blue); endfor; endfig ;
Файл должен закончиться командой end. или bye. Эти команды дают понять интерпретатору mpost, что обработка закончена.
АвтоматизацияПравить
Для автоматизации получения картинок с помощью MetaPost можно использовать следующий Makefile:
#временный файл tmp_file := tmp_file #программы LATEX := latex MPOST := mpost -tex=latex DVIPS := dvips MPTOPDF := mptopdf MV := mv all: @echo "run: make mpfile.n.[eps|pdf] - where n is the picture number" %.eps: % @echo "\documentclass[12pt]{minimal}">$(tmp_file).tex @echo "\usepackage[koi8-r]{inputenc}">>$(tmp_file).tex @echo "\usepackage[english,russian]{babel}">>$(tmp_file).tex @echo "\usepackage{graphicx}">>$(tmp_file).tex @echo "\DeclareGraphicsRule{*}{eps}{*}{}">> $(tmp_file).tex @echo "\nofiles">>$(tmp_file).tex @echo "\begin{document}">> $(tmp_file).tex @echo "\thispagestyle{empty}">> $(tmp_file).tex @echo "\includegraphics{$(basename $@)}">> $(tmp_file).tex @echo "\end{document}">> $(tmp_file).tex @$(LATEX) $(tmp_file) @$(DVIPS) -E -o $@ $(tmp_file) @rm $(tmp_file).* %.pdf: % @$(MPTOPDF) $< @$(MV) `echo $< | sed -e "s/\.\([0-9]\+\)$$/-\1.pdf/"` $<.pdf clean: @rm -f mpx* *~ *.log *.mpx @rm -f $(tmp_file).* #Зависимости для mpost-картинок. #По одной для каждого числа из beginfig %.1: %.mp $(MPOST) $< … %.64: %.mp $(MPOST) $<
Чтобы на выходе получить готовую eps-картинку с уже «внедрёнными» шрифтами, которую можно вставить уже куда угодно, достаточно выполнить следующую команду:
> make <имя mp-файла>.<номер картинки>.[eps|pdf]
Обычно mp-файлам даются короткие имена.
Чуть-чуть о METAПравить
В качестве базового языка, инструкции которого подаются на вход программы MetaPost, используется язык META.
В MetaPost можно оперировать следующими типами данных:
- boolean — логический (Истина/Ложь)
- numeric — обычные числа
- pen (перо) — то, чем компьютер рисует (в подавляющем большинстве случаев используется круглое перо pencircle)
- pair (точка) — пара чисел (x, y) в случае декартовых координат или R*dir(α) в случае полярных координат
- path (путь) — набор точек с описанием типа соединений между ними
- color (цвет) — тройка чисел (r, g, b) соответствует цветовой модели RGB
- picture (картинка) — совокупность путей и точек
- string (строка) — ASCII строка,
- transform (линейные преобразования) — линейные преобразования, которые можно применять к объектам типа pair, pen, path и picture.
Имена переменных в META могут состоять из нескольких лексем. Лексемы могут быть либо буквенными, либо числовыми. Например, переменная x1l состоит из трёх лексем. Её можно переписать более понятным способом x[1].l, то есть числовая лексема по сути указывает на номер элемента в массиве, а следующая за ней буква уточняет элемент структуры. Возможность опускать «[].» в написании имён переменных упрощает в некоторых случаях восприятие кода (например,
Все переменные необходимо объявлять перед использованием. Исключением являются переменные типа numeric. Массивы объявляются и используются следующим образом:
pair w[]; w1:=(10,5); w[2]=w[1];
Взаимодействие переменных, чисел и операторов вполне естественно, но достаточно нетривиально. Описание этого достойно отдельного раздела. В любом случае следует действовать по правилу: если сомневаетесь, то расставляйте скобки в нужных местах.
В META можно опускать некоторые из операторов для сокращения записей, например, 2*x соответствует записи 2x. Но будьте осторожны, так как 1/2x -- это 0.5x, что более естественно с точки зрения математики, но не программирования. В META сначала обрабатываются числовые лексемы.
Набор стандартных вычислительных операций расширен с учётом специализации языка. В частности, поддерживаются операции пифагорова сложения
В языке присутствуют операторы цикла, условных переходов и тому подобное. Отличительной особенностью META является возможность решать линейные уравнения. Например, выражение вида
Программу mpost можно использовать в режиме калькулятора для вычислений на языке META. Это позволяет проверить правильность ваших предположений относительно языка. Пример сеанса представлен ниже:
baldin@evgueni:~$ mpost This is MetaPost, Version 0.901 (Web2C 7.5.5) **\relax *a:=10; *b:=8; *c:=a+-+b; *show c; >> 6 *show (3-sqrt 5)/2; >> 0.38197 *show angle(1,sqrt 3); >> 60.00008 *show 2**10; >> 1024.00003 *show infinity; >> 4095.99998 *show epsilon; >> 0.00002 *show infinity-infinity; >> 0 *end Transcript written on mpout.log.
После вывода приглашения ** следует набрать команду \relax. Далее можно вводить команды MetaPost. Делать это надо аккуратно, так как этот режим не поддерживает «истории команд». В начале не предполагалось, что MetaPost можно использовать и так тоже. С помощью команды show можно вывести результат на экран. Закончить сеанс можно с помощью команды end. Обратите внимание, что на просьбу вывести бесконечность (infinity) MetaPost выдал 4095.99998 — это максимальное значение, которое может принимать переменная типа numeric. Причём в процессе вычисления результат может превышать «бесконечность», но ответ должен быть меньше или равен ей, иначе будет выдана ошибка. Минимальный шаг изменения типа numeric равен epsilon, или, точнее, 1/256/256. При создании рисунка эти ограничения не существенны, так как диапазон изменения чисел вполне велик, чтобы вместить все элементы. Но в любом случае это тоже необходимо учитывать.
Если Вы хотите вычислить однострочное выражение, то на первоначальное приглашение ** можно ввести expr. В этом случае mpost считает файл expr.mf и на любое ваше действие будет выдаваться ответ:
baldin@evgueni:~$ mpost This is MetaPost, Version 0.901 (Web2C 7.5.5) **expr (/usr/local/texlive/2005/texmf-dist/metafont/base/expr.mf gimme an expr: 2(a+3b)-2b >> 4b+2a gimme an expr: 1/3[a,b] >> 0.33333b+0.66667a
ПримерыПравить
Внимание: Код каждого примера приведён в описании соответствующей картинки — достаточно щёлкнуть по ней кнопкой мыши.
- Узор из черепашек.png
Узор из черепашек. Пример использования объекта picture (картинка).
Треугольник Паскаля. Пример вставки текста.
- Циклоида.png
Траектории точек на колесе во время поступательного движения без проскальзывания. Пример использования цикла.
- Число постов на LOR.png
Число постов на LOR от номера месяца в году. Пример простого графика.
- Фрактальные лесопосадки.png
Фрактальные узоры. Пример рекурсии.
- Распределение вещества во вселенной.png
Распределение вещества во вселенной. Пример круговой диаграммы
АналогиПравить
MetaPost имеет некоторое количество ограничений, доставшихся ему в наследство от METAFONT. Попытка обойти эти ограничения легла в основу создания программного интерпретатора Asymptote. Язык, используемый Asymptote, похож на META, но вследствие перехода от синтаксиса макро-языка к синтаксису C++ гораздо более многословен и сложен. Основное преимущество Asymptote заключается в лучшей поддержке возможностей PostScript.
Functional MetaPost — DSL для графики встроенный в Haskell, который генерирует код MetaPost. Подробности на страничке Functional MetaPost
METAGRAF — графический интерфейс над MetaPost. Написан на Java. По возможностям напоминает xfig. Картинки сохраняет в формате MetaPost. Подробности на страничке METAGRAPH
Книги на русскомПравить
ЛитератураПравить
- Дональд Кнут. Все про METAFONT = The METAFONTbook. — М.: «Вильямс», 2003. — С. 384. — ISBN 5-8459-0442-0.
- Информация о MetaPost: М. Гуссенс, С. Ратц и Ф. Миттельбах. Путеводитель по пакетам LaTeX и его графическим расширениям = The LaTeX Graphics Companion. — М.: МИР, 2002. — С. 621. — ISBN 5-03-003388-2.
- Джон Д. Хобби. METAPOST: руководство пользователя = A user's manual for MetaPost. — 2008. — С. 105.
СсылкиПравить
- Ошибка Lua в Модуль:Citation/CS1 на строке 4511: bad argument #1 to 'pairs' (table expected, got nil).
- Ошибка Lua в Модуль:Citation/CS1 на строке 4511: bad argument #1 to 'pairs' (table expected, got nil).
- Ошибка Lua в Модуль:Citation/CS1 на строке 4511: bad argument #1 to 'pairs' (table expected, got nil).
- Домашняя страничка Джона Хобби http://cm.bell-labs.com/who/hobby/index.html и его же страничка с основопологающими статьями по MetaPost http://cm.bell-labs.com/who/hobby/MetaPost.html
- Ошибка Lua в Модуль:Citation/CS1 на строке 4511: bad argument #1 to 'pairs' (table expected, got nil).
- Ошибка Lua в Модуль:Citation/CS1 на строке 4511: bad argument #1 to 'pairs' (table expected, got nil).
- Ошибка Lua в Модуль:Citation/CS1 на строке 4511: bad argument #1 to 'pairs' (table expected, got nil).
- ru_metapost — русское ЖЖ-сообщество о MetaPost.
Первоисточник этой статьи был признан «хорошей статьёй» русского раздела Википедии. |