Estou usando a biblioteca de autômatos do TiKZ e colocando linhas entre os nós com 18 pontos de espessura. O problema é que a fronteira entre as linhas e o estado não se ajusta bem:
Eu gostaria de ter isso
Alguma ideia?
Aqui está um exemplo mínimo produzindo o primeiro:
\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}
Responder1
Aqui está uma tentativa com pontas de seta.
(Também tenho uma solução com decorações, mas elas me confundem mais do que pontas de flechas.)
Infelizmente, a Round Cap
ponta da seta apenas adiciona (ou remove com a reversed
opção) um semicírculo do final da linha. Isso funcionaria muito bem se a largura da linha fosse duas vezes o raio de um nó circular.
O setup code
para a ponta da seta Hug Cap
calculaum pouco de matemáticae salva três valores:
- raio (isto é obtido da tecla de seta
length
), - h, esta é a inserção (a altura) e
- um ângulo (afinal, é um arco que é desenhado).
Existe a possibilidade de estender a definição da ponta da seta para incluir opções como reversed
, open
, left
, etc.
O deround
estilo calcula o raio a partir de nós circulares. (Embora esta resposta seja inspirada no circle connection bar
estilo e na decoração da mindmap
biblioteca, ela usa uma abordagem diferente para extrair o raio de nós já existentes.)
Obviamente, os caminhos devem ser ortogonais à borda dos círculos.
Esta solução deve ser usada com os operadores to
/ edge
(usa \tikztostart
e \tikztotarget
para automatizar os cálculos dos raios. Não use outro line caps
senão butt
(o padrão), isso também pode ser verificado dentro da definição da ponta da seta.
Isso quebra se a largura da linha for maior que o diâmetro e também para raios muito grandes (mas então por que usar isso mesmo?).
Código
\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}
Saída
Responder2
Encontrei um jeito, mas não parece ser o canônico, apenas um jeito que funciona: Usando camadas, e depois aumentando o comprimento da linha:
\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}
EDITAR Segunda solução, baseada no comentário abaixo (use o centro como coordenada em vez de linhas mais longas)
\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}