LaTeX

индекс
144,89

Диаграммы в LaTeX

Многие достаточно часто сталкиваются с необходимостью создания различных диаграмм, графов, деревьев для удобного представления информации. Особенно важным этот вопрос может оказаться при создании презентаций. Большинство офисных пакетов предоставляют возможность создавать красивые диаграммы при помощи интерактивного интерфейса. А если нужно создать большую диаграмму? Или записать в ней математические формулы? Сосредоточиться на содержании, а не оформлении и расположении элементов на экране?

Преимущества использования LaTeX уже неоднократно обсуждались. Так же как и способы создания презентаций при помощи beamer и векторная графика из пакета PGF/Tikz. Но возможно ли получить в LaTeX диаграммы, не уступающие по внешнему виду полученным в больших и сложных пакетах? Один из способов предложен ниже.

Начало


Для начала нам потребуется LaTeX (для Windows подойдет MiKTeX, для Linux или Mac — TeXlive), а также пакеты beamer и tikz. Оба входят в комплект поставки MiKTeX. Скачать последние версии можно либо со страниц проектов, либо из CTAN. Также потребуются базовые знания о LaTeX, и использовании в нем этих пакетов. Поскольку beamer ориентирован на использование pdflatex, использоваться будет в основном именно PDF.

Простая диаграмма


Попробуем сделать небольшую и простую диаграмму. В качестве примера возьмем последовательное преобразование форматов при работе LaTeX: .tex > .dvi > .ps > .pdf. Допустим у нас уже есть документ, в который надо эту диаграмму поместить. В преамбуле подключаем пакет tikz и подключаем нужные библиотеки. В данном случае нам потребуются positioning и arrows, которые нужны для расположения элементов друг относительно друга и рисования стрелок между ними соответственно.
\usepackage{tikz}
\usetikzlibrary{positioning,arrows}
Необходимо заметить, что при перечислении имен библиотек через запятую не допускаются пробелы. Это связано с тем, что tikz подставляет строку полностью как часть имени файла с библиотекой.
В нужном месте документа добавляем окружение tikzpicture, внутри которого перечисляются команды tikz. Каждая команда должна оканчиваться точкой с запятой. Команды могут быть вложенными, например для создания стрелки с подписью или дочерних элементов. Общий синтаксис команды:
\command [parameters] (name) {contents} arguments;
где
  • command — собственно команда;
  • parameters — параметры команды через запятую;
  • name — имя создаваемого объекта;
  • contents — содержание объекта (может включать другие объекты);
  • arguments — аргументы, например точки пути или размеры, а также другие команды (но уже без обратного слеша).
Все части, кроме самой команды, необязательны. В tikz сотни команд, интересными для нас будут path и node.
Команда \path создает «контур» в терминологии векторной графики. В качестве параметра указывается что именно следует сделать с этим контуром:
  • draw — только нарисовать контур;
  • fill — только залить;
  • fill,draw — нарисовать контур и залить;
  • use as bounding box — использовать контур как ограничение размера для картинки.
Также указать на наличие и направление стрелок <-, ->, <->, цвет, толщину линии и другие параметры, полный перечень можно прочитать в документации к пакету.
В качестве аргументов передаются координаты, через которые контур должен проходить. В tikz существует много вариантов задания координат:
  • относительные координаты точки (1,5);
  • реальные на листе, во всех форматах LaTeX (10pt, 3mm);
  • использование полярных и даже введение собственной системы координат;
  • относительно предыдущей точки ++(0,1);
  • относительно начальной точки +(-1,2);
  • относительно именованного объекта (name).
Точки, между которыми требуется провести линию разделяются оператором --. Наиболее подходящим к идеологии LaTeX является позиционирование относительно объектов. Например для рисования связи между краями объектов foo и bar достаточно выполнить команду
\path (foo) edge (bar);

Команда \node создает узел (или объект), как правило содержащий некий текст. Её параметрами могут быть стиль текста, цвет, информация о наличии, форме и цвете очертаний, расположение относительно других объектов и многие другие. Расположить узел в конкретном месте с координатами (x, y) можно при помощи аргумента at (x, y). Но наиболее интересным является расположение относительно других объектов, предоставляемое библиотекой positioning. Для его использования достаточно указать в параметрах в каком направлении относительно другого объекта должен находиться данный. Например
\node (foo) {foo};
\node[right of=foo] (bar) {bar};

Более подробную информацию можно получить в документации. Перечисленного вполне достаточно, чтобы создать первую несложную диаграмму. В ней должно быть 4 объекта, и 3 стрелки между ними. Реализация выглядит так
\node       (tex) {.tex};
\node[right of=tex] (dvi) {.dvi};
\node[right of=dvi] (ps)  {.ps};
\node[right of=ps]  (pdf) {.pdf};

\path[->] (tex) edge (dvi);
\path[->] (dvi) edge (ps);
\path[->] (ps)  edge (pdf);



Улучшаем диаграмму


Первая картинка у нас уже получилась, но она совершенно не смотрится: смещенная линия текста, отсутствие рамок вокруг текста, слишком близко расположенные объекты. И это вместо красивых картинок с градиентами и прозрачностью? Диаграмму определенно стоит улучшить, и для этого мы воспользуемся заданием стилей. Стиль задается при помощи команды
\tikzstyle{name} = [parameters]
Имя стиля потом может быть передано как параметр другой команды. Для дальнейшей работы нам также потребуется подключить библиотеки shapes и shadows. Хорошей фигурой для текста будет прямоугольник со скругленными краями, который имеется в библиотеке. Для него дополнительно потребуется описать фон и контур. Прежде чем это сделать, давайте разберемся со способами задания цвета в tikz.
Цвет может задаваться названием из предопределенных в LaTeX и пакете xcolor. Также можно определить свой RGB-цвет при помощи команды
\definecolor{name}{rgb}{0.5,0.5,0.5}
Через запятую указаны RGB-компоненты и их количество от 0 до 1. Или в других системах, о чем можно подробнее прочитать в документации пакета xcolor. Также предопределенные цвета можно смешивать. Синтаксис этой операции таков:
color1!percent!color2
В результате получится цвет, содержащий percent% первого цвета и (100-percent)% второго. Если второй не указан — по умолчанию используется белый цвет. Смешивание цветов можно повторять, не сохраняя промежуточный цвет, например
red!50!black!50!white
Сначала будет получен цвет из 50% красного и 50% черного, а потом результат смешан с 50% белого. В результирующем красного и черного цветов окажется по 25%.

Теперь можем перейти непосредственно к заданию стиля
\tikzstyle{format} = [rounded rectangle,
                      thick,
                      minimum size=1cm,
                      draw=red!50!black!50,
                      top color=white,
                      bottom color=red!50!black!20,
                      font=\itshape,
                      drop shadow]
Данный стиль предписывает нарисовать прямоугольник со скругленными краями, жирной линией контура с цветом red!50!black!50, залить его используя градиент сверху вниз от белого цвета до red!50!black!20, с тенью, внутренний текст печатать курсивом.
Далее нам следует выровнять базовую линию текста. Для этого сначала разберемся, почему он оказался смещенным. Слова «tex», «ps» и «pdf» имеют разную высоту, и соответственно различным образом были отцентрованы внутри объекта. Таким образом явное задание высоты текста должно решить эту проблему.
Окружение tikzpicture также позволяет задавать параметры, которые действуют для всех команд внутри этого окружения. Воспользуемся этим и зададим в нем толщину линии связи, минимальное расстояние между объектами и параметры высоты текста.
\begin{tikzpicture}[thick,
                    node distance=2cm,
                    text height=1.5ex,
                    text depth=.25ex]
\node[format]  (tex) {.tex};
\node[format,right of=tex] (dvi) {.dvi};
\node[format,right of=dvi] (ps)  {.ps};
\node[format,right of=ps]  (pdf) {.pdf};

\path[->] (tex) edge (dvi);
\path[->] (dvi) edge (ps);
\path[->] (ps)  edge (pdf);
\end{tikzpicture}



Усложняем задачу


Теперь, когда мы получили приемлемый вариант простой диаграммы попробуем усложнить задание. Добавим в эту диаграмму способы представления данных (на экране и печатная) и возможности преобразования без промежуточных форматов. Поскольку линий на диаграмме будет немало, то стоит их подписать.
Определим другой стиль узла для способа представления данных. Пусть это будет эллипс с синим градиентом сверху вниз, темно-синим контуром и тенью. Описание стиля будет похожим на предыдущее.
\tikzstyle{format} = [ellipse,
                      thick,
                      minimum size=1cm,
                      draw=blue!50!black!50,
                      top color=white,
                      bottom color=blue!50!black!20,
                      drop shadow]

Но при добавлении дополнительных линий возникает ещё одна проблема. Если задать путь от (tex) до (pdf) tikz по умолчанию проведет его прямой линией, что нас совершенно не устраивает. К сожалению, использовать возможности graphviz пакет пока не умеет, поэтому придется самим описывать путь вокруг элементов. Для этого будем использовать относительное задание путей.
\path[->, draw] (tex) -- +(0,2) -| (pdf);
\path[->, draw] (dvi) -- ++(0,1) -- ++(3,0) -- (pdf);
Первый контур начинается от узла (tex) и поднимается на 2 относительные единицы вверх. После чего продолжается вправо до образования перпендикуляра к узлу (pdf) и опускается к нему. Второй контур начинается от узла (dvi), поднимается на 1 единицу, идет вправо на 3 единицы относительно предыдущей точки, и по прямой направляется к узлу (pdf). Для добавления подписей к контурам воспользуемся вложенными командами и добавим узел к контуру:
\path[->, draw] (tex) -- +(0,2) -| node[near start] {pdf\LaTeX} (pdf);

Но данная команда добавит объект таким образом, чтобы центры контура и узла совпали. Текст окажется перечеркнутым линией связи. Чтобы этого не произошло в окружении tikzpicture укажем параметр автоматического позиционирования подписей auto. Теперь описание нашей диаграммы примет вид
\begin{tikzpicture}[thick,
                    node distance=3cm,
                    text height=1.5ex,
                    text depth=.25ex,
                    auto]
\node[format]       (tex) {.tex};
\node[format,right of=tex] (dvi) {.dvi};
\node[format,right of=dvi] (ps)  {.ps};
\node[format,right of=ps]  (pdf) {.pdf};
\node[medium,below of=dvi]  (screen) {screen};
\node[medium,below of=ps]   (verbatim) {verbatim};

\path[->] (tex) edge node {\LaTeX} (dvi);
\path[->] (dvi) edge node {dvips}(ps);
\path[->] (ps)  edge node {ps2pdf} (pdf);
\path[->] (dvi) edge node {xdvi} (screen);
\path[->] (ps) edge node[near start] {gs} (screen);
\path[->] (pdf) edge (screen);
\path[->] (ps) edge node {print} (verbatim);
\path[->] (pdf) edge (verbatim);
\path[->, draw] (tex) -- +(0,2) -| node[near start] {pdf\LaTeX} (pdf);
\path[->, draw] (dvi) -- ++(0,1) -- node[near start] {dvipdf} ++(3,0) -- (pdf);
\end{tikzpicture}



Используем в презентации


Полученную диаграмму можно использовать как статическую картинку в статье или описании. Но для презентации часто требуется, чтобы объекты диаграммы появлялись в определенном порядке. В LaTeX для создания презентаций используется пакет beamer. Его работа строится вокруг понятия оверлеев — различных представлений одного и того же слайда. Об использовании beamer уже писали, поэтому вспомним о спецификации оверлеев. Их можно добавить практически к любой команде LaTeX, и команды tikz не исключение. Поэтому любые иллюстрации, полученные с помощью этого пакета легко разделяются на части и интегрируются с beamer. Однако сейчас команды расположены не совсем удобно для добавления оверлеев. Если потребуется, чтобы одновременно появлялись объект и все его связи с уже существующими, придется добавлять спецификации к каждой из команд. Логичнее было бы расположить команды последовательно по времени появления на слайде. На помощь тут приходит возможность группировать команды, о которой было сказано в самом начале. В команде \path можно указать узлы, которые она будет соединять. Таким образом мы можем сделать по одной команде на каждый оверлей.
\begin{frame}
\frametitle{\LaTeX workflow}
\begin{tikzpicture}[thick,
                    node distance=3cm,
                    text height=1.5ex,
                    text depth=.25ex,
                    auto]

\path[use as bounding box] (-1,0) rectangle (10,-2);
\path[->]<1-> node[filename] (tex) {.tex};
\path[->]<2-> node[filename, right of=tex] (dvi) {.dvi}
              (tex) edge node {\LaTeX} (dvi);
\path[->]<3-> node[display, below of=dvi] (screen) {screen}
              (dvi) edge node {xdvi} (screen);
\path[->]<4-> node[filename, right of=dvi] (ps) {.ps}
              (dvi) edge node {dvips} (ps);
\path[->]<5-> (ps) edge node {gs} (screen);
\path[->]<6-> node[display, below of=ps] (verbatim) {verbatim}
              (ps) edge node {print} (verbatim);
\path[->]<7-> node[filename, right of=ps] (pdf) {.pdf}
              (ps) edge node {ps2pdf} (pdf);
\path[->]<8-> (pdf) edge (screen)
                    edge (verbatim);
\path[->, draw]<9-> (tex) -- +(0,2) -| node[near start] {pdf\LaTeX} (pdf);
\path[->, draw]<10-> (dvi) -- ++(0,1) -- node[near start] {dvipdf} ++(3,0) -- (pdf);
\end{tikzpicture}
\end{frame}



Что получилось в результате можно посмотреть здесь.
_________
При подготовке использованы
PGF/Tikz manual
Xcolor manual
Beamer manual
The TeX workflow example
_________
Текст подготовлен в ХабраРедакторе
+55
24 января 2010, 17:12
79

комментарии (17)

0
CristobalJunta #
Спасибо! Очень полезно.
+1 Вам в карму.

Кстати, похожая заметка уже была — habrahabr.ru/blogs/latex/48260/
0
ftynse #
Поэтому я старался акцентировать внимание на построении диаграмм и последующем их использовании в beamer.
Также, если это будет интересно, могу написать о использовании цепочек (chains) и деревьев из tikz. Просто в рамках одной статьи не уместилось.
0
ulysses #
Да, если можно про цепочки и деревья — с удовольствием прочту. Всё-таки хорошего user manual по TikZ я для себя так и не нашёл (хотя просмотрел несоклько версий), так что роюсь в 500-страничной документации, как слепой котёнок.
0
korkholeh #
Интересная статья. Спасибо.
0
sigizmund #
Браво, отлично, очень полезная статья и очень вовремя!!!
0
clamaw #
О! Отличная статья, люблю tex.
0
adontz #
Блин, красиво как элементы расположены. Никак не могу заставить этот долбаный graphviz делать так же!
0
intelligenceAgent #
Давно хочу перейти на ТеХ. Но, блин, он все таки довольно нетривиален в освоении, и это потребует немало времени. Времени, которое нужно будет отобрать у своей основной деятельности. А его и так не хватает.
И что я получу на выходе. Будет потрачено много времени и усилий, буду писать статьи и отчеты красиво и по правильному, а в итоге шеф скажет, вышли мне в ворде, чтобы я мог отредактировать. Или конференция какая-нибудь доморощенная отечественная скажет мы не знаем, что это такое.
И все бы ничего, если бы только был нормальный конвертер. Но сколько ни читал на эту тему, везде пишут, что все равно придется дорабатывать напильником. А это опять же драгоценное время.
0
ftynse #
С конвертерами, к сожалению, проблема есть. TeX все же разрабатывался как система компьютерной верстки.
В сфере моей деятельности (учеба и небольшие проекты) большинство документов оформляется одним человеком. Рецензии, если таковые нужны, практически всегда делаются на печатной копии. Если требуется совместное редактирование с кем-либо — используем систему контроля версий, исходник же текстовый. Людей, не знакомых с TeX'ом, прошу просто написать нужный текст, а форматированием занимаюсь уже сам.

Можно пробовать использовать комментарии к PDF в качестве заметок. Но это все равно требует изменения в способе работы и других людей. Что касается просмотра готовых документов — хоть какая-нибудь программа просмотра PDF есть практически на всех компьютерах, с этим проблем пока не возникало.
0
corristo #
в избранное
0
ganqqwerty #
прелестно, большое спасибо! Вот как раз пишу презентацию для диплома в LaTeX. Кстати, кто знает, отчего широкие таблицы tabular в beamer могут выезжать за правый край? Третий час воюю.
0
bryndin #
похоже на вот этот пример с www.texample.net :-)
все бы хорошо, только написание кода времени много занимает, а его обычно нет совсем. в итоге рисую в Dia.
0
ftynse #
Диаграмма действительно оттуда, нужна была простая и понятная. Даже ссылка на него в конце статьи есть ;-)

Сначала на код уходило действительно прилично времени. Потом появились уже готовые стили и немного опыта в представлении как это будет выглядеть после компиляции. Стало немного быстрее. Но решающим фактором в выборе именно этого инструмента стала простота интеграции с beamer.
0
maxcom #
gnuplot вроде тоже уже научился диаграммы рисовать
0
o_O_Tync #
Спасибо, очень интересно! Я уж было думал придётся оставаться с не слишком удобным xymatrix :)
0
sigizmund #
Еще раз хочу написать спасибо автору — делая курсовую сегодня, вспомнил об этом посте и родил:

\subsection{Looking up ``s*ng''}
In this case we need to lookup terms with a wildcard in a middle of a term. Hence, we need to permutate it to the form with a trailing wildcard. Process of searching for such permutation is shown in Figure~\ref{fig:perm_sng}.

\begin{figure}[h]
\begin{center}
\begin{tikzpicture}[thick,
                    node distance=2cm,
                    text height=1.5ex,
                    text depth=.25ex]
    \node[format]       (sng) {\texttt{s*ng}};
    \node[format, right of=sng] (sng1) {\texttt{s*ng\$}};
    \node[format, right of=sng1] (sng2){\texttt{*ng\$s}};
    \node[format, right of=sng2] (sng3){\texttt{ng\$s*}};
    
    \path[->] (sng) edge (sng1);
    \path[->] (sng1) edge (sng2);    
    \path[->] (sng2) edge (sng3);        
    \path[->, draw] (sng1) -- ++(0,1) -- ++(3,0) -- (sng3);
\end{tikzpicture}
\end{center}
\caption{Permutations for wildcard query \texttt{s*ng}}\label{fig:perm_sng}
\end{figure}


Получилось очень классно — именно то, что и требовалось!
0
w495 #
Спасибо за статью, благодаря ей, я открыл для себя Tikz. Если это возможно, расскажите, пожалуйста, как можно использовать mind maps c помощью tikz. У меня пока получилось так:

image

Но не уверен, что это все делал верно.

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