Сети PETRI
NODE
и настройки своих стилей.Categories:
Установка необходимых библиотек для работы
\documentclass{article} % say
\usepackage{tikz}
\usetikzlibrary{arrows.meta,decorations.pathmorphing,backgrounds,positioning,fit,petri}
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (1,1);
\end{tikzpicture}
\end{document}
NODE
и настройки своих стилей.
Просто нарисуем в системе координат 5 node
\begin{tikzpicture}
\path ( 0,2) node [shape=circle,draw] {}
( 0,1) node [shape=circle,draw] {}
( 0,0) node [shape=circle,draw] {}
( 1,1) node [shape=rectangle,draw] {}
(-1,1) node [shape=rectangle,draw] {};
\end{tikzpicture}
Но, выяснилось, что вариант выше не очень умен по своей сути. \path
задает координату откуда начинается какое-то действие, в нашем случае размещаем node
, а можно draw
, но node
с параметром draw
обернет текст рамкой.
Синтаксис at
т.е. поместить в…
\begin{tikzpicture}
\path node at ( 0,2) [shape=circle,draw] {}
node at ( 0,1) [shape=circle,draw] {}
node at ( 0,0) [shape=circle,draw] {}
node at ( 1,1) [shape=rectangle,draw] {}
node at (-1,1) [shape=rectangle,draw] {};
\end{tikzpicture}
Получаем тотже эффект, но говорят умнее.
Дальше больше:
\begin{tikzpicture}
\path node at ( 0,2) [circle,draw] {}
node at ( 0,1) [circle,draw] {}
node at ( 0,0) [circle,draw] {}
node at ( 1,1) [rectangle,draw] {}
node at (-1,1) [rectangle,draw] {};
\end{tikzpicture}
Прикручиваем стили
\begin{tikzpicture}[thick]
\path node at ( 0,2) [circle,draw=blue,fill=red] {}
node at ( 0,1) [circle,draw=blue,fill=yellow] {}
node at ( 0,0) [circle,draw=blue,fill=green] {}
node at ( 1,1) [rectangle,draw=black!50,fill=black!20] {}
node at (-1,1) [rectangle,draw=black!50,fill=black!20] {};
\end{tikzpicture}
Причем
[draw=blue]
— рисует такого цвета обводку, а fill
— заполняет пространство
А теперь сделаем стиль универсальным на блок
\begin{tikzpicture}
[place/.style={circle,draw=blue!50,fill=blue!20,thick},
transition/.style={rectangle,draw=black!50,fill=black!20,thick}]
\node at ( 0,2) [place] {};
\node at ( 0,1) [place] {};
\node at ( 0,0) [place] {};
\node at ( 1,1) [transition] {};
\node at (-1,1) [transition] {};
\end{tikzpicture}
просто один будет называться place
а второй transition
и теперь название этихстилей ставим в описании node
.
Размеры SHAPE
Можно задать переменную inner sep=2mm
в блоке — и это сделает отступ вокруг текста 2mm. Или:
[place/.style={circle,draw=blue!50,fill=blue!20,thick,
inner sep=0pt,minimum size=6mm},
т.е прямо в стиль и это даст эффект, что размер будет не меньше 4мм, пока в него влезает текст.
Имена SHAPEs
Очень пригодятся имена SHAPEs для того,чтобы иметь привязки и потом на них ссылаться.
\begin{tikzpicture}
\node (waiting 1) at ( 0,2) [place] {};
\node (critical 1) at ( 0,1) [place] {};
\node (semaphore) at ( 0,0) [place] {};
\node (leave critical) at ( 1,1) [transition] {};
\node (enter critical) at (-1,1) [transition] {};
\end{tikzpicture}
имена будут в круглых скобочках, причем порядок написания не имеет значения. Это все определения одного \path
Нативное размещение SHAPEs
Вместо указания координат, можно указывать влево, вправо, ниже, выше. Такого ума можно набраться в библиотеке: \usetikzlibrary {positioning}
\usetikzlibrary {positioning}
\begin{tikzpicture}
\node[place] (waiting) {};
\node[place] (critical) [below=of waiting] {}; % ниже waitinig
\node[place] (semaphore) [below=of critical] {}; % ниже critical
\node[transition] (leave critical) [right=of critical] {}; % справа от critical
\node[transition] (enter critical) [left=of critical] {}; % слева от critical
\end{tikzpicture}
Объекты размещаются по координатной сетке.
Метки объектов по сторонам света
Все объекты TIKZ получают метки по сторонам света:
- north
- south
- west
- east
- north east
- north west
- south east
- south west
\node [red,above] at (semaphore.north) {$s\le 3$};
\end{tikzpicture}
напишет node красного цвета red
над above
северной меткой объекта semaphore
.
но в библиотеке есть вариант с label
, который сделает тоже самое.
\node[place] (semaphore) [below=of critical,
label=above:$s\le3$] {};
Памятка, как label
работает:
\tikz
\node [circle,draw,label=60:$60^\circ$,label=below:$-90^\circ$] {my circle};
И немного подольем красочки: label={[red]below:$-90^\circ$}
и будет метка красная, но чтобы небыло конфлика поставим все это дело в {}
.
Коннекторы это просто
\draw [->] (enter critical.east) -- (critical.west);
\draw [->] (waiting.west) .. controls +(left:5mm) and +(up:5mm)
.. (enter critical.north);
т.е. \draw [в какую сторону стрелу] (координата откуда) -- (координата куда);
Краткий комментарий к .. CONTROLS ..
Это вставка вместо оператора рисования - -, которая позволяет поставить несколько контрольных точек относительно некоторого центра вращения и сказать куда они сдвигаются и насколько:
\draw[->](waiting.west) ..controls +(left:15mm) and +(up:15mm) .. (enter critical.north);
Умность библиотеки tirz
Можно не указывать стороны света в метках, от сделает это автоматически
\draw [->] (enter critical) -- (critical);
\draw [->] (waiting) .. controls +(left:5mm) and +(up:5mm)
.. (enter critical);
будет тоже самое.
Совершенствуем стрелочки до предела (to [in out])
Замечательный оператор to
, который укажет под каким углом выйти и под каким углом войти стрелке.
Схема такая же, только вместо наших - -
и .. controls ..
появляется еще один оператор to [out=,in=]
in=220 — выглядит еще причудлевее.
\draw[->](waiting) to [out=0, in=180] (leave critical)
Команда bend right left
изгиб кривой.
\draw[->](leave critical) to [bend left=150] (semaphore)
но лучше загибать bend left=45
, правда лучше.
Теперь еще один элемент EDGE
край - ребро, как угодно, но эта штука действует как внутри \path
так и самостоятельно. Т.е. можно задавать свои особые наконечники и цвета для edge
.
\node[transition] (enter critical) [left=of critical] {}
edge [->] (critical)
edge [<-,bend left=45] (waiting)
edge [->,bend right=45] (semaphore);
буквально: там где нарисовал node
от неё начинаю рисовать edges
.
- не завершая
node
точкой с запятой пишемedge
- [здесь команды куда стрела, как гнуть]
- (куда соединяем)
- теперь текущая точка опять в пункте
node
- продолжаем рисовать дальше от той же точки
Вот такой казус может получиться:
\begin{tikzpicture}
\node (c) at (0,0) {};
\node (n) at (0,1) {}
edge [bend right=45] (w);
\node (s) at (0,-1) {}
edge [bend right=45] (e);
\node (w) at (-1,0) {}
edge [bend right=45] (s);
\node (e) at (1,0) {}
edge [->,bend right=45] (n);
\end{tikzpicture}
Но если рисовать по задумке:
\begin{tikzpicture}
\node (c) at (0,0) {};
\node (n) at (0,1) {};
\node (w) at (-1,0) {}
edge [bend left=45] (n);
\node (s) at (0,-1) {}
edge [bend left=45] (w);
\node (e) at (1,0) {}
edge [bend left=45] (s)
edge [bend right=45] (n);
\end{tikzpicture}
то получим ->
И все это упакуем в стили
[bend angle=45,
pre/.style={<-,shorten <=1pt,>={Stealth[round]},semithick},
post/.style={->,shorten >=1pt,>={Stealth[round]},semithick}]
вот такая штука позволит дальше в коде писать просто:
edge [pre] (critical)
и edge [post,bend right] (waiting)
и TIKZ все поймет.
Метки на линиях
\begin{tikzpicture}[auto,bend right]
\node (a) at (0:1) {$0^\circ$};
\node (b) at (120:1) {$120^\circ$};
\node (c) at (240:1) {$240^\circ$};
\draw (a) to node {1} node [swap] {1'} (b)
(b) to node {2} node [swap] {2'} (c)
(c) to node {3} node [swap] {3'} (a);
\end{tikzpicture}
- NODE — нарисовали метки в узлах через оператор
at
, т.е. поместить в … конкретную точку - DRAW — рисует через оператор
to
, т.е. от одной точки к другой, а на пути его рисования мы размещаем другие NODE и говорим с какой стороны их рисовать относительно линии. - SWAP — это нарисовать зеркально
- на пути DRAW, NODEs может быть сколько угодно, главное их всех разместить правильно, а то все в одну точку вляпаются.
Декоративные линии (\usetikzlibrary {decorations.pathmorphing})
Собственно любую линию можно нарисовать, просто отдельно нужно изучить особенности этой библиотеки.
\usetikzlibrary {decorations.pathmorphing}
\begin{tikzpicture}
\draw [->,decorate,
decoration={snake,amplitude=.4mm,segment length=2mm,post length=1mm}]
(0,0) -- (3,0);
\end{tikzpicture}
получится вот такая кривулина:
И продолжая тему кривулины или любой другой линии, если мне нужно разместить текст, то делаю в разрыве DRAW вставку NODE:
node [above,text width=3cm,align=center,midway]
{
replacement of the \textcolor{red}{capacity} by
\textcolor{red}{two places}
}
- above — выше над линией
- text width=3cm — ширина текста 3см
- align-center — текст выравнять по центру
- midway — в центре линии (у него еще есть братья:
- near start — pos=0.25.
- near end — pos=0.75.
- very near start — pos=0.125.
- very near end — pos=0.875.
- at start — pos=0.
- at end — pos=1
BACKGROUND или слои и фон под картинкой
Нам поможет библиотека fit
и background
fit
— дает координаты всех узлов
background
— размещает на разных слоях рисунки
Еще нам понадобятся знания об окружении SCOPE
— это просто окружение чего-то, такие своеобразные скобки, в которых будут действовать правила, которые мы установим, а за пределами SCOPE
все возвращается в исходные установки.
\begin{tikzpicture}[ultra thick]
\begin{scope}[red]
\draw (0mm,10mm) -- (10mm,10mm);
\draw (0mm,8mm) -- (10mm,8mm);
\end{scope}
\draw (0mm,6mm) -- (10mm,6mm);
\begin{scope}[green]
\draw (0mm,4mm) -- (10mm,4mm);
\draw (0mm,2mm) -- (10mm,2mm);
\draw[blue] (0mm,0mm) -- (10mm,0mm);
\end{scope}
\end{tikzpicture}
этот пример на линиях все показал
а про background мы просто добавим в конце такой код:
\begin{scope}[on background layer]
\node [fill=black!30,fit=(waiting) (critical) (semaphore)
(leave critical) (enter critical)] {};
\end{scope}
on background layer
— на каком слое разместить, т.е. под рисунком\node
— рисуем nodefill
— заполняем ее цветомfit
— перечисляем все внутренние node по которым определяем координаты
Настройки стандартных библиотек для рисования сетей PETRI
\begin{tikzpicture}
[node distance=1.3cm,on grid,>={Stealth[round]},bend angle=45,auto,
every place/.style= {minimum size=6mm,thick,draw=blue!75,fill=blue!20},
every transition/.style={thick,draw=black!75,fill=black!20},
red place/.style= {place,draw=red!75,fill=red!20},
every label/.style= {red}]
т.е. там уже все определено, поэтому нарисуем все, что уже пытались с использованием библиотеки:
\usetikzlibrary {arrows.meta,petri,positioning}
\node [place,tokens=1] (w1) {};
\node [place] (c1) [below=of w1] {};
\node [place] (s) [below=of c1,label=above:$s\le 3$] {};
\node [place] (c2) [below=of s] {};
\node [place,tokens=1] (w2) [below=of c2] {};
\node [transition] (e1) [left=of c1] {}
edge [pre,bend left] (w1)
edge [post,bend right] (s)
edge [post] (c1);
\node [transition] (e2) [left=of c2] {}
edge [pre,bend right] (w2)
edge [post,bend left] (s)
edge [post] (c2);
\node [transition] (l1) [right=of c1] {}
edge [pre] (c1)
edge [pre,bend left] (s)
edge [post,bend right] node[swap] {2} (w1);
\node [transition] (l2) [right=of c2] {}
edge [pre] (c2)
edge [pre,bend right] (s)
edge [post,bend left] node {2} (w2);
а это ее более кудрявый друг:
\usetikzlibrary {arrows.meta,petri,positioning}
\begin{scope}[xshift=6cm]
\node [place,tokens=1] (w1') {};
\node [place] (c1') [below=of w1'] {};
\node [red place] (s1') [below=of c1',xshift=-5mm]
[label=left:$s$] {};
\node [red place,tokens=3] (s2') [below=of c1',xshift=5mm]
[label=right:$\bar s$] {};
\node [place] (c2') [below=of s1',xshift=5mm] {};
\node [place,tokens=1] (w2') [below=of c2'] {};
\node [transition] (e1') [left=of c1'] {}
edge [pre,bend left] (w1')
edge [post] (s1')
edge [pre] (s2')
edge [post] (c1');
\node [transition] (e2') [left=of c2'] {}
edge [pre,bend right] (w2')
edge [post] (s1')
edge [pre] (s2')
edge [post] (c2');
\node [transition] (l1') [right=of c1'] {}
edge [pre] (c1')
edge [pre] (s1')
edge [post] (s2')
edge [post,bend right] node[swap] {2} (w1');
\node [transition] (l2') [right=of c2'] {}
edge [pre] (c2')
edge [pre] (s1')
edge [post] (s2')
edge [post,bend left] node {2} (w2');
\end{scope}
и на финише фон:
\begin{scope}[on background layer]
\node (r1) [fill=black!10,rounded corners,fit=(w1)(w2)(e1)(e2)(l1)(l2)] {};
\node (r2) [fill=black!10,rounded corners,fit=(w1')(w2')(e1')(e2')(l1')(l2')] {};
\end{scope}
\draw [shorten >=1mm,->,thick,decorate,
decoration={snake,amplitude=.4mm,segment length=2mm,
pre=moveto,pre length=1mm,post length=2mm}]
(r1) -- (r2) node [above=1mm,midway,text width=3cm,align=center]
{replacement of the \textcolor{red}{capacity} by \textcolor{red}{two places}};
\end{tikzpicture}
получим такую красоту: