MetaPost

MetaPost
Изображение логотипа
Класс языка императивный
Появился в 1994
Автор Джон Хобби
Выпуск 1.8 (17 июня 2013)
Тестовая версия 2.0rc2 (19 февраля 2018)
Система типов неявная, динамическая, строгая
Испытал влияние METAFONT
Повлиял на Asymptote
Лицензия GNU LGPL
Сайт tug.org/metapost
Логотип Викисклада Медиафайлы на Викискладе

MetaPost — интерпретатор языка программирования META, который можно использовать для создания графических иллюстраций. MetaPost был создан Джоном Хобби в то время, когда он был аспирантом у Дональда Кнута. В качестве основы была взята система создания шрифтов METAFONT[1].

На входе интерпретатору подаётся текст на META, а на выходе получается графический файл в формате PostScript[2]. Начиная с версии 1.200 MetaPost поддерживает в качестве выходного формата SVG-графику[3].

Язык META, унаследованный от METAFONT, позволяет оперировать геометрическими объектами, такими как: точка, путь, картинка и выполнять над ними различные алгебраические действия, например, сдвиг, вращение и другие линейные преобразования.

Основными отличиями MetaPost от METAFONT кроме выходного формата является наличие поддержки цвета и возможность делать текстовые вставки. Текстовые вставки создаются с помощью TeX, таким образом, любая конструкция, которая может быть создана в TeX, также может быть вставлена в картинку MetaPost. Кроме этого изначально автор MetaPost Джон Хобби разработал библиотеку METAOBJ (“metapost Objects”) для визуализации двумерных графиков[4][5].

Интерпретатор MetaPost (исполняемый файл mpost) вместе со стандартными макро-библиотеками распространяется как открытое программное обеспечение, обычно, в составе дистрибутивов TeX.

MetaPost-конвейер

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 указывается порядковый номер картинки. При компиляции этот номер будет добавляться к картинке как расширение. Пример:

Hello World
Hello World
%Математический 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-файлам даются короткие имена.

Как вариант, предлагается shell-скрипт (mp2pdf.sh), который делает практически то же самое. Предполагается использование GNU/Linux (или подобной ОС).

Скрипт для каждого beginfig(n)-блока сделает файлы filen.eps и filen.pdf, где file — имя исходного MetaPost-файла, n — номер блока. В скрипте предусмотрено размещения полученных файлов в отдельных каталогах. Имена каталогов задаются переменными EPS_DIR и PDF_DIR. Если каталогов с такими именами не существуют, то скрипт автоматически создаёт их.

#!/bin/sh
# Скрипт для превращения MetaPost файла в EPS и PDF рисунки

# каталоги для хранения eps- и  pdf-файлов
EPS_DIR=./eps
PDF_DIR=./pdf
TMP_FILE=tmp

if [[ "$@" == ""]];
then
  echo 
  echo Скрипт обрабатывает mp-файл, создает eps- и pdf-файлы и
  echo перемещает их соответственно в каталоги $EPS_DIR и $PDF_DIR
  echo Использование: ./mp2pdf.sh file.mp
  echo
  exit
fi

if [ ! -d $EPS_DIR ]; then
  echo ======== Создание каталога для eps-файлов 
  mkdir $EPS_DIR
fi
if [ ! -d $PDF_DIR ]; then
  echo ======== Создание каталога для pdf-файлов
  mkdir $PDF_DIR
fi

echo ======== Исходный файл: $@

list=`grep beginfig $1 | sed -e 's/beginfig(//' -e 's/);//'`
echo ======== Список блоков:  $list

echo ======== Запуск mpost...
mpost -tex=latex $1

for i in $list          # цикл по блокам beginfig()
do
 epsi=${1%mp}$i
 eps=${1%.mp}${i}.eps
 pdf=${1%.mp}${i}.pdf
 echo Блок ${i}: ' >> ' $epsi ' >> ' $eps ' >> ' $pdf

if [ ! -e $epsi ]; then
  echo
  echo Ошибки при обработке mp-файла!
  echo
  exit
else
  echo ======== MetaPost ===== Ok!
fi

echo ======== Генерация временного LaTeX-файла...
echo \\documentclass[12pt]{article} > ${TMP_FILE}.tex
echo \\usepackage{mathtext} >> ${TMP_FILE}.tex
echo \\usepackage{amsmath} >> ${TMP_FILE}.tex
echo \\usepackage[T2A]{fontenc} >> ${TMP_FILE}.tex
echo \\usepackage[koi8-r]{inputenc} >> ${TMP_FILE}.tex
echo \\usepackage[english,russian]{babel} >> ${TMP_FILE}.tex
echo \\usepackage{graphics} >> ${TMP_FILE}.tex
echo \\begin{document} >> ${TMP_FILE}.tex
echo \\pagestyle{empty} >> ${TMP_FILE}.tex
echo \\includegraphics{${epsi}} >> ${TMP_FILE}.tex
echo \\end{document} >> ${TMP_FILE}.tex

echo ======== Запуск LaTeX...
latex ${TMP_FILE}

if [ ! -e ${TMP_FILE}.dvi ]; then
  echo
  echo ======== Не найден dvi-файл!
  echo
  exit
else
  echo ======== LaTeX ===== Ok!
fi
echo ======== Запуск dvips...
dvips -E ${TMP_FILE} -o $eps

echo ======== Запуск epstopdf...
epstopdf $eps

if [[ -e $pdf]]; then
 mv $eps $EPS_DIR 
 mv $pdf $PDF_DIR
 echo ======== Перенос $eps и $pdf в нужное место...
fi

echo ======== Зачистка...
rm *.log *.mpx ${TMP_FILE}.* *.aux *.dvi *.tex $epsi 2>>/dev/null

done

Скрипт надо сделать исполняемым:

chmod +x ./mp2pdf.sh

Использование:

./mp2pdf.sh file.mp

Пример MetaPost-файла для тестирования:

%% Шаблон для mp-файлов
prologues:=0;

% LaTeX; работает вместе с "mpost -tex=latex file.mp" (см. скрипт выше)
verbatimtex \documentclass[12pt]{article}
\usepackage{mathtext}
\usepackage{amsmath}
\usepackage[T2A]{fontenc}
\usepackage[koi8-r]{inputenc}
\usepackage[english,russian]{babel}
\begin{document}
etex;

beginfig(1);
draw (0,0)--(0,100)--(100,100)--(100,0)--cycle;
label(btex Метка: $\alpha_1$ etex, (50,50));
endfig;

end.

Язык META

В качестве базового языка, инструкции которого подаются на вход программы MetaPost, используется язык META[6].

В 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, то есть числовая лексема по сути указывает на номер элемента в массиве, а следующая за ней буква уточняет элемент структуры. Возможность опускать «[].» в написании имён переменных упрощает в некоторых случаях восприятие кода (например, x 1 l {\displaystyle x_{1l}}  — это x-координата границы линии слева по направлению движения для первой точки пути z[]) и сокращает объём программы. Взамен, если нужны просто переменные без подобных особенностей, то придётся ограничиться только буквенными комбинациями.

Все переменные необходимо объявлять перед использованием. Исключением являются переменные типа numeric. Массивы объявляются и используются следующим образом:

 pair w[];
 w1:=(10,5);
 w2:=w1;

Взаимодействие переменных, чисел и операторов вполне естественно, но достаточно нетривиально. Описание этого достойно отдельного раздела. В любом случае следует действовать по правилу: если сомневаетесь, то расставляйте скобки в нужных местах.

В META можно опускать некоторые из операторов для сокращения записей, например, 2*x соответствует записи 2x. При этом 1/2x — это 0.5x, что более естественно с точки зрения математики, но не программирования. В META сначала обрабатываются числовые лексемы.

Набор стандартных вычислительных операций расширен с учётом специализации языка. В частности, поддерживаются операции пифагорова сложения a + + b = a 2 + b 2 {\displaystyle a{+}{+}b={\sqrt {a^{2}+b^{2}}}} , пифагорова вычитания a + + b = a 2 b 2 {\displaystyle a{+}{-}{+}b={\sqrt {a^{2}-b^{2}}}} , целочисленное деление div и возведение в степень x y = x y {\displaystyle x{*}{*}y=x^{y}} .

В языке присутствуют операторы цикла, условных переходов и тому подобное. Отличительной особенностью META является возможность решать системы линейных уравнений. Например, выражение вида C = 1 / 2 [ A , B ] {\displaystyle C=1/2[A,B]} , означает, что точка C находится ровно посередине между точками А и B.

Программу 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

Примеры

  • Лого MetaPost на Википедии.
    Лого MetaPost на Википедии.
  • Узор из черепашек. Пример использования объекта picture (картинка).
    Узор из черепашек. Пример использования объекта picture (картинка).
  • Треугольник Паскаля. Пример вставки текста.
    Треугольник Паскаля. Пример вставки текста.
  • Траектории точек на колесе во время поступательного движения без проскальзывания. Пример использования цикла.
    Траектории точек на колесе во время поступательного движения без проскальзывания. Пример использования цикла.
  • Пример использования линейных преобразований.
    Пример использования линейных преобразований.
  • Число постов на LOR от номера месяца в году. Пример простого графика.
    Число постов на LOR от номера месяца в году. Пример простого графика.
  • Фрактальные узоры. Пример рекурсии.
    Фрактальные узоры. Пример рекурсии.
  • Распределение материи во Вселенной. Пример круговой диаграммы
    Распределение материи во Вселенной. Пример круговой диаграммы

Код каждого примера приведён в описании соответствующей картинки.

Известен пример нестандартного применения программы. С 1996 по 1999 год авторы спелеопрограммы Therion[7] написали DSL METAPOST для преобразования 2D-карт в 3D-модели пещер, а все подписи реализовали в формате TEX[8].

Аналоги

MetaPost имеет некоторое количество ограничений, доставшихся ему в наследство от METAFONT. Попытка обойти эти ограничения легла в основу создания программного интерпретатора Asymptote[9]. Язык, используемый Asymptote, похож на META, но вследствие перехода от синтаксиса макро-языка к синтаксису C++ гораздо более многословен и сложен. Основное преимущество Asymptote заключается в лучшей поддержке возможностей PostScript.

Functional MetaPost — DSL для графики встроенный в Haskell, который генерирует код MetaPost.[10]

METAGRAF — графический интерфейс над MetaPost. Написан на Java. По возможностям напоминает xfig. Картинки сохраняет в формате MetaPost.[11]

Среди программного окружения LaTeX аналогичной MetaPost функциональностью также обладают пакеты PSTricks и PGF/TikZ.

На основе программной базы MetaPost был создан инструмент METATYPE1 для разработки Type1 шрифтов.

Примечания

  1. John D. Hobby, A METAFONT-like System with PostScript Output, Tugboat, the TeX User's Group Newsletter, 10(4), 1989.  (неопр.) Дата обращения: 4 января 2011. Архивировано из оригинала 15 мая 2012 года.
  2. John D. Hobby, Introduction to MetaPost, Proceedings of EuroTeX '92, 1992. Архивная копия от 15 мая 2012 на Wayback Machine MetaPost is a picture-drawing language very much like METAFONT except with PostScript output. The language provides access to all major features of Level 1 PostScript® and it has facilities for integrating graphics with typeset text.
  3. MetaPost 1.200 announcement  (неопр.). Дата обращения: 4 января 2011. Архивировано 5 сентября 2014 года.
  4. John D. Hobby, Drawing Graphs with MetaPost, AT&T Bell Laboratories Computing Science Technical Report 164, 1992.  (неопр.) Дата обращения: 4 января 2011. Архивировано из оригинала 15 мая 2012 года.
  5. Источник  (неопр.). Дата обращения: 31 июля 2022. Архивировано 31 июля 2022 года.
  6. Е.М. Балдин Введение в MetaPost Архивная копия от 4 сентября 2016 на Wayback Machine // Linux Format 76 (февраль 2006)
  7. About Therion  (неопр.). therion.speleo.sk. Дата обращения: 25 ноября 2022. Архивировано 4 декабря 2022 года.
  8. Глубокие последствия: краткий экскурс в высокотехнологичную спелеологию  (рус.). Хабр. Дата обращения: 25 ноября 2022. Архивировано 24 ноября 2022 года.
  9. Asymptote: A vector graphics language John C. Bowman and Andy Hammerlindl, TUGBOAT: The Communications of the TeX Users Group, 29:2, 288-294 (2008).  (неопр.) Дата обращения: 4 января 2011. Архивировано 17 июля 2011 года.
  10. Functional MetaPost  (неопр.). Дата обращения: 3 сентября 2006. Архивировано из оригинала 13 ноября 2008 года.
  11. METAGRAPH  (неопр.). Дата обращения: 3 сентября 2006. Архивировано 31 августа 2006 года.

Ссылки

  • MetaPost on the Web (англ.). TEX users group. Дата обращения: 1 января 2011. Архивировано из оригинала 8 февраля 2012 года.
  • Евгений Балдин. Создание иллюстраций в MetaPost  (неопр.) (2006). — Цикл статей в журнале Linux Format. Дата обращения: 1 января 2011. Архивировано из оригинала 20 марта 2012 года.
  • Джон Хобби и участники проекта развития MetaPost. A User’s Manual for MetaPost 1.212 (англ.). TEX users group (19 октября 2010). Дата обращения: 1 января 2011. Архивировано из оригинала 8 февраля 2012 года.
  • Джон Хобби и участники проекта развития MetaPost/ Пер. Владимира Лидовского. MetaPost руководство пользователя (A User’s Manual for MetaPost 1.004)  (рус.). CTAN (10 мая 2008). Дата обращения: 5 января 2011. Архивировано из оригинала 8 февраля 2012 года.
  • Домашняя страничка Джона Хобби
  • Основополагающие статьи по MetaPost Джона Хобби
  • André Heck. Руководство пользователя MetaPost (англ.). MAPS (2005). Дата обращения: 5 января 2011. Архивировано из оригинала 8 февраля 2012 года.
  • Vincent Zoonekynd. Metapost : exemples (фр.) (2003). — Большое количество примеров. Дата обращения: 5 января 2011. Архивировано из оригинала 8 февраля 2012 года.
  • Jean-Michel Sarlat. Galeries MetaPost (фр.) (11 декабря 2005). — Фракталы, геометрия, картинки «под Эшера». Дата обращения: 5 января 2011. Архивировано из оригинала 8 февраля 2012 года.
  • Создание векторных картинок в MetaPost https://habr.com/post/423571/

Литература

  • Дональд Кнут. Всё про METAFONT = The METAFONTbook. — М.: Вильямс, 2003. — 384 с. — ISBN 5-8459-0442-0.
  • М. Гуссенс, С. Ратц, Ф. Миттельбах. Путеводитель по пакетам LaTeX и его графическим расширениям = The LaTeX Graphics Companion. — М.: Мир, 2002. — 621 с. — ISBN 5-03-003388-2.
  • Е. М. Балдин. Создание иллюстраций в MetaPost.
  • Джон Хобби и команда разработки MetaPost. METAPOST Руководство пользователя. — 1.004.1.



Перейти к шаблону «Свободная типографика»
Гарнитуры операционных систем
Другие гарнитуры
Программное обеспечение
Лицензии
Группы и люди
  • Категория:Свободные шрифты
Перейти к шаблону «TeX navbox»
ΤΕΧ
Макропакеты
Альтернативные движки ΤΕΧ
Дистрибутивы
Сообщество
  • CTAN
  • TUGboat
  • The PracTeX Journal
  • Deutschsprachige Anwendervereinigung TeX
Разное