Векторная графика в LaTeX. Пакет PGF/TikZ

    Доброго времени суток. Давно собирался рассказать о возможностях векторной графики в LaTeX, предоставляемых низкоуровневым макропакетом PGF и его расширением TikZ, а выход предыдущей статьи о пакете Xy-pic для создания диаграмм и графов и появление свободного времени сделали возможным начать работу :-).

    Мне в своё время понадобилось найти и изучить какое-то гибкое средство для создания качественных векторных изображений, потому что уже достали криво масштабированные, вставленные с ужасным расширением картинки растровых форматов, портящие всё впечатление от документа, да и увеличивающие его размер в два раза из-за одной большой картинки с прямоугольником и несколькими подписями к нему. Имеющиеся возможности встроенного окружения picture весьма скудны; пакет PStricks ориентирован на язык PostScript (не работает с pdflatex, который мне необходим), хотя и может кое-что, чего не может PGF; система MetaPost, пожалуй, является наиболее мощной из всех в этой области, но функционирует с использованием отдельного интерпретатора со всеми вытекающими из этого последствиями. Таким образом, выбор пал на PGF/TikZ.



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

    Очень приятно, когда для какого-то инструмента есть исчерпывающий список примеров, что он может делать и как этого достичь. Для обсуждаемого пакета этот список можно посмотреть, набрав в поисковике «pgf examples» и перейдя по первой же ссылке. Здесь все примеры одним списком: www.texample.net/tikz/examples/all. Нет смысла пытаться описать всё, на что способен пакет. Пожалуй, остановлюсь на основных концепциях.

    В статье рассматривается использование pgf/tikz вместе с макропакетом LaTeX, как самым распространённым, однако pgf/tikz также работает и с другими. Текст статьи базируется преимущественно на руководстве TikZ & PGF. Manual for Version 2.00 (560 с.). Некоторые примеры взяты из него. Также в книге есть небольшая, но полезная глава Guidelines on Graphics (с. 65), посвящённая общим принципам работы над документами с векторной графикой, включая примеры того, как надо и как не надо делать; к ней стоит обратиться независимо от того, будете ли вы в дальнейшем использовать pgf/tikz или что-то другое.

    Установка


    В GNU/Linux надо поставить пакет pgf (и зависимый xcolor версии >= 2.00). Если такого нет, достаточно разархивировать исходники (локально или глобально) и сделать texhash (подробности см. в руководстве). В Windows pgf/tikz входит в состав дистрибутива MiKTeX, так что ничего дополнительного устанавливать не требуется.

    Трансляция


    Для получения pdf используем
    pdflatex file.tex

    Для получения ps используем две команды:
    latex file.tex
    dvips file.dvi

    Также интересна возможность конвертации в HTML и SVG.

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


    Для использования базовых возможностей пакета надо подключить его в преамбуле командой
    \usepackage{tikz}


    Для вставки команд pgf/tikz используется либо команда \tikz с одним аргументом (обычно для вставки рисунка в пределах строки), либо окружение \begin[options]{tikzpicture}...\end{tikzpicture}. Если в аргументе к \tikz надо указать несколько команд рисования, они окружаются фигурными скобками (\tikz[options]{...}). Каждая команда оканчивается точкой с запятой.
    \documentclass{memoir}<br>
    \pagestyle{empty}<br>
    \usepackage{tikz}<br>
    <br>
    \begin{document}<br>
    \tikz{\draw (-1,-1) -- (1,1); \path[fill=green!80!blue,draw=red] (0,0) circle (7mm);}<br>
    \end{document}



    Очень удобно, что не надо указывать размер холста. Программа сама вычислит его за вас.

    Точки


    Точки задаются абсолютно или относительно. Примеры декартовых и полярных координат:
    • (2,0) — точка с заданными координатами в текущих единицах измерения (по умолчанию — 1 см);
    • (2cm,-3pt) — 2 см в направлении Ox, –3 пункта в направлении Oy;
    • (30:5cm) — точка на расстоянии 5 см от текущего положения в направлении 30 градусов;
    • +(2,0) — точка, отстоящая от текущего положения на 2 единицы вправо (текущее положение не меняется);
    • ++(2,0) — точка, отстоящая от текущего положения на 2 единицы вправо, которая становится новым текущим положением.

    \tikz \draw (0,0) --  +(1,0) --  +(0,1) --  +(1,1);<br>
    \tikz \draw (0,0) -- ++(1,0) -- ++(0,1) -- ++(1,1);<br>
    \tikz \draw (1,0) -- (0,0) -- (30:1);



    Также могут использоваться барицентрические координаты, система координат узлов (см. ниже), тангенциальная система.

    Система координат пересечений позволяет оперировать с координатами пересечения (однако, пока только для комбинаций прямых и окружностей). Для этого задаётся первый и второй объекты (или линии их координатами) и номер пересечения (когда их несколько).
    \begin{tikzpicture}<br>
      \draw[help lines] (0,0) grid (3,2);<br>
      \draw (0,0) coordinate (A) -- (3,2) coordinate (B)<br>
            (1,2) -- (3,0);<br>
      \fill[red] (intersection of A--B and 1,2--3,0) circle (2pt);<br>
    \end{tikzpicture}



    Можно задавать координаты с использованием относительных или абсолютных модификаторов длины или проекций. Это делается следующими способами:
    • coordinate!number!angle:second_coordinate
    • coordinate!dimension!angle:second_coordinate
    • coordinate!projection_coordinate!angle:second_coordinate

    Например,
    • (1,2)!.25!(3,4) означает координату, которая находится на расстоянии одной четверти пути из (1,2) в (3,4)
    • (1,2)!1cm!(3,4) означает координату, которая находится на расстоянии 1 см от точки (1,2) на прямой (1,2)--(3,4)
    • (1,2)!(0,5)!(3,4) означает координату, которая является проекцией точки (0,5) на прямую (1,2)--(3,4)


    Траектории


    Траектория — это последовательность прямых и кривых линий. Они создаются командой \path. Если она вызывается без аргументов, то ничего нарисовано не будет, что не очень интересно. Аргументами могут быть draw, fill, shade, clip или любая их комбинация. Вместо \path[draw], \path[fill], \path[shade,draw],… можно использовать сокращения \draw, \fill, \shadedraw.

    Основная команда для создания прямых — это (a) -- (b), где (a) и (b) — некоторые точки.

    Кубическая кривая Безье задаётся командой (a) .. controls (x) and (y) .. (b), где (a) и (b) — некоторые точки, (x) и (y) — опорные точки, влияющие на форму кривой. Если часть and (y) пропустить, считается, что (y) = (x).

    Графические параметры


    Они указываются в квадратных скобках (как необязательные аргументы в LaTeX) в виде наборов ключ-значение: key=value. Например, \tikz \draw[line width=2pt,color=red] (1,0) -- (0,0) -- (1,0) -- cycle;. Иногда часть key= можно опускать, если ключ для данного значения трактуется однозначно.

    Узлы


    Текст и подписи добавляются к рисунку в виде узлов (nodes). Они привязываются к текущему положению на плоскости (в пространстве), либо явно привязываются к некоторой точке. В качестве параметров можно указать якорь привязки узла (где он будет относительно точки: справа, слева, справа сверху и т.п.), форму узла (круг, квадрат, эллипс, ...), способ его отображения (нарисовать, залить) и другие.
    \tikz \draw (1,1) node {text} -- (2,2);


    \begin{tikzpicture}[line width=2pt]<br>
      \draw (0,0) node [below left]  {$A$} -- <br>
            (1,0) node [below right] {$B$} -- <br>
            (1,1) node [above right] {$C$} -- <br>
            (0,1) node [above left]  {$D$} -- <br>
            cycle;<br>
    \end{tikzpicture}



    Области видимости


    С помощью окружения scope можно создавать области видимости со своими параметрами; остальные наследуются из содержащей данную. Фактически, окружение tikzpicture ведёт себя аналогично scope. С определёнными ограничениями области видимости можно также применять при рисовании траектории.
    \tikz \draw (0,0) -- (1,1)<br>
                {[rounded corners] -- (2,0) -- (3,1)} -- <br>
                (3,0) -- (2,1);



    Стили


    Стили указываются при перечислении графических параметров. Есть набор уже определённых, которые можно переопределять. Можно определять свои.
    \begin{tikzpicture}[scale=0.7]<br>
      \draw             (0,0) grid +(2,2);<br>
      \draw[help lines] (3,0) grid +(2,2);<br>
    \end{tikzpicture}



    Вычисления


    При подключении библиотеки calc командой в преамбуле
    \usetikzlibrary{calc}

    можно использовать некоторые математические вычисления для определения координат, например,
    \begin{tikzpicture}[scale=0.5]<br>
      \draw[help lines] (0,0) grid (4,3);<br>
      \fill [red]   ($2*(1,1)$)              circle (2pt);<br>
      \fill [green] (${1+1}*(1,.5)$)         circle (2pt);<br>
      \fill [blue]  ($cos(0)*sin(90)*(1,1)$) circle (2pt);<br>
      \fill [black] (${3*(4-3)}*(1,0.5)$)    circle (2pt);<br>
    \end{tikzpicture}



    Заключение


    Возможности пакета можно перечислять ещё очень долго (например, я ничего не упоминал про графы, деревья и цепи), но такому перечислению не место в одной статье, тем более, что существует вышеупомянутый сайт и прекрасное руководство с исчерпывающими примерами использования каждой вкусности пакета pgf/tikz. Использовать его или нет — решать вам. Я с ним работаю меньше шести месяцев (да и узнал о нём не намного раньше), но уже активно использую и не жалею; во многих случаях он сильно экономил время и силы. Если у народа возникнет интерес, рассказ может быть продолжен ;-)

    PS.
    Изображения делались так:
    $ latex qq.tex && dvips -K -o qq.ps qq.dvi && convert -antialias -seed 0 -density 200 -trim qq.ps qq.png
    

    Подсветка делалась экспортом из gvim (тема emacs).
    Поделиться публикацией

    Комментарии 17

      +6
      Благодарю проголосовавших за предоставление возможности перенести в блог LaTeX.
        +4
        очень красивая статья получилась, после такого хочется вновь взяться за tex :)
          +3
          Я в этом ничего не понимаю, но выглядит чертовски красиво. Особенно первый график. :)
            0
            Он был взят из примеров; создан путём вовлечения в процесс проги gnuplot (кривые и прямая построены по точкам).
          0
          Математическая природа — бисплайны, я так понимаю.
            0
            Отличная тема, отличная статья, спасибо автору. Жаль только мои ТеХ-документы гораздо более скучные и не требуют такой красивой векторной графики. Картинки, которые я вставляю, как правило, являются постскриптами из внешних программ/скриптов/окружений.

            Вопрос такой возник: вы говорите, что «PStricks ориентирован на язык PostScript (не работает с pdflatex, который мне необходим)» — а нельзя разве ему просто сделать dvipdf после того как latex сгенерит .dvi?
              0
              http://www.tug.org/PSTricks/main.cgi?file=pdf/pdfoutput:
              ps2pdf
              This is the absolutely easiest way to convert a complete document or a single PSTricks image to pdf:

              ps2pdf <file>.ps

              dvipdf is no alternative, because it cannot handle the PostScript prologue files. Use always dvips and then ps2pdf.

              If you use a gui for creating your document, then set your output profile to LaTeX=>PS=>PDF, then your gui does it all.

              По собственному опыту убедился, что чем больше шагов вида <a>to<b> для получения итога, тем больше вероятность, что что-то где-то будет не так. Да и зачем использовать ps, если нужен только pdf?)
              +1
              Отличная статья! Спасибо!
              P. S. А ещё из неё я узнал про ХабраРедактор)))
                0
                Расскажите, а чем ненравится tex->ps->pdf, тогда и pdf получается и PSTricks можно использовать. Я обычно рисую в иллюстраторе, а потом надписи через PSTricks добавляю.
                  0
                  У меня были проблемы конвертации отдельных .ps в .pdf, например, с отступами. LaTeX требует картинок в формате eps, а у меня они в основном в png. Мне кажется, PStricks похож на PGF, но над pgf есть удобная для использования надстройка TikZ.

                  Не говорю, что мне чем-то не нравится конкретно PStricks, просто нужно было средство, удовлетворяющее вышеупомянутым свойствам; я его частично изучил и теперь решил описать. Как только появится время и необходимость, обязательно познакомлюсь и с PStricks)
                    0
                    У меня с конвертацией проблемрое не было. А pdflatex прямо png кушает без конвертации?
                      +1
                      А pdflatex прямо png кушает без конвертации?

                      Да. eps он как раз не кушает.
                  +1
                  А pdflatex прямо png кушает без конвертации?

                  Да. eps он как раз не кушает.
                    0
                    Спасибо. Интересная статья. Каждый раз когда открываю мануал по pgf восхищаюсь их картинками.
                    Особенный бонус pgf-а — это возможность работы совместно с beamer-ом. А именно рисовать картинки «по частям».
                    Эта функциональность просто незаменима, если рассказываешь какие-нибудь алгоритмы (особенно на графах, конечно =)).
                      0
                      а существует гуи для метапоста?
                        0
                        Не слышал о таком. Ценность Metapost именно в описании рисунка в виде алгоритма его построения с использованием переменных, циклов, динамически вычисляемых точек пересечения и т.п.

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                      Самое читаемое