Я использую библиотеку автоматов TiKZ и размещаю линии между узлами толщиной 18pt. Проблема в том, что граница между линиями и состоянием не очень хорошо совпадают:
Я хотел бы иметь это
Есть идеи?
Вот минимальный пример создания первого варианта:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{automata}
\begin{document}
\begin{tikzpicture}[thick]
\node[state] (1) {};
\draw[-, blue!20, line width=18pt] (1) to (0,1);
\end{tikzpicture}
\end{document}
решение1
Вот попытка с наконечниками стрел.
(У меня также есть решение с украшениями, но они сбивают меня с толку больше, чем наконечники стрел.)
К сожалению, Round Cap
наконечник стрелки добавляет (или удаляет с reversed
опцией) только полукруг с конца линии. Это будет работать отлично, если ширина линии в два раза больше радиуса круглого узла.
Для setup code
наконечника стрелы Hug Cap
вычисляетсянемного математикии сохраняет три значения:
- радиус (берется из клавиши со стрелкой
length
), - час, это вставка (высота), и
- угол (в конце концов, это дуга, которая рисуется).
Существует возможность расширить определение наконечника стрелки, включив такие параметры, как reversed
, open
, left
и т. д.
Стиль deround
вычисляет радиус из круговых узлов. (Хотя этот ответ вдохновлен стилем circle connection bar
и оформлением из mindmap
библиотеки, в нем используется другой подход для извлечения радиуса из уже существующих узлов.)
Очевидно, что траектории должны быть ортогональны границе окружности.
Это решение необходимо использовать с операторами to
/ (оно использует и для автоматического вычисления радиусов. Не используйте ничего, кроме ( по умолчанию), это также можно проверить внутри определения наконечника стрелки.edge
\tikztostart
\tikztotarget
line caps
butt
Это нарушается, если ширина линии больше диаметра, а также при очень больших радиусах (но тогда зачем вообще это использовать?).
Код
\documentclass[tikz]{standalone}
\usetikzlibrary{automata,arrows.meta}
\pgfdeclarearrow{
name=Hug Cap,
parameters=\the\pgfarrowlength,
setup code={
% h = r - .5 sqrt(4 r^2 - s^2)
\pgfmathsetlengthmacro\pgfarrowh{\pgfarrowlength-.5*sqrt(4*\pgfarrowlength*\pgfarrowlength-\pgflinewidth*\pgflinewidth}
% a = asin(s / (2 r))
\pgfmathsetmacro\pgfarrowangle{asin(\the\pgflinewidth/(2*\the\pgfarrowlength))}
\pgfarrowssavethe\pgfarrowlength % radius
\pgfarrowssave\pgfarrowh % h
\pgfarrowssave\pgfarrowangle % a
\pgfarrowsupperhullpoint{0pt}{.5\pgflinewidth}
\pgfarrowsupperhullpoint{\pgfarrowh}{.5\pgflinewidth}
\pgfarrowssetlineend{.1pt} % eeh :\
},
drawing code={
\pgfpathmoveto{\pgfqpoint{\pgfarrowh}{-.5\pgflinewidth}}
\pgfpatharc{180+\pgfarrowangle}{180-\pgfarrowangle}{\pgfarrowlength}
\pgfpathlineto{\pgfqpoint{0pt}{.5\pgflinewidth}}
\pgfpathlineto{\pgfqpoint{0pt}{-.5\pgflinewidth}}
\pgfpathclose
\pgfusepathqfill}}
\makeatletter
\def\qrr@tikz@circle{circle}
\newcommand*\qrr@getRadius[1]{%
\def\qrr@radius{0pt}%
\tikz@scan@one@point\pgfutil@firstofone(#1)\relax
\iftikz@shapeborder
\edef\qrr@shape{\csname pgf@sh@ns@\tikz@pp@name{\tikz@shapeborder@name}\endcsname}%
\ifx\qrr@tikz@circle\qrr@shape
% ah circle, get the radius!
\begingroup
\csname pgf@sh@np@\tikz@pp@name{\tikz@shapeborder@name}\endcsname
\let\qrr@radius\radius
\pgfmath@smuggleone\qrr@radius
\endgroup
\fi
\fi}
\tikzset{
deround/.style={
/utils/exec={%
\qrr@getRadius\tikztostart
\ifdim\qrr@radius=0pt
\def\qrr@arrowsettings{-}\else
\edef\qrr@arrowsettings{{Hug Cap[length=+\qrr@radius]}-}\fi
\qrr@getRadius\tikztotarget
\ifdim\qrr@radius=0pt\else
\edef\qrr@arrowsettings{\qrr@arrowsettings{Hug Cap[length=+\qrr@radius]}}\fi
},
arrows/.expanded=\qrr@arrowsettings}
}
\makeatother
\begin{document}
\begin{tikzpicture}[thick]
\node[state] (1) {};
\node[state] at (2,1) (2) {abcdef};
\path[line width=12pt, every edge/.append style=deround]
(2) edge (1)
edge[line width=10pt, red, out=150, in=90] (1);
\path[line width=12pt] (1) edge[out=180-30, in=180+30, looseness=4, deround] (1);
\end{tikzpicture}
\end{document}
Выход
решение2
Я нашел способ, но он, похоже, не канонический, а просто работающий: использование слоев и последующее увеличение длины линии:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{automata}
\begin{document}
\pgfdeclarelayer{bg}
\pgfsetlayers{bg,main}
\begin{tikzpicture}[thick]
\node[state,fill=white] (1) {};
\begin{pgfonlayer}{bg}
\draw[-,shorten >=-4pt,shorten <=-4pt,blue!20, line width=18pt]
(1) to (0,1);
\end{pgfonlayer}
\end{tikzpicture}
\end{document}
РЕДАКТИРОВАТЬ Второе решение, основанное на комментарии ниже (используйте центр в качестве координаты вместо более длинных линий)
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{automata}
\begin{document}
\pgfdeclarelayer{bg}
\pgfsetlayers{bg,main}
\begin{tikzpicture}[thick]
\node[state,fill=white] (1) {};
\begin{pgfonlayer}{bg}
\draw[-,blue!20, line width=18pt]
(1.center) to (0,1);
\end{pgfonlayer}
\end{tikzpicture}
\end{document}