Estoy usando la biblioteca de autómatas de TiKZ y coloco líneas entre nodos de 18 puntos de grosor. El problema es que la frontera entre las líneas y el Estado no encaja bien:
me gustaria tener esto
¿Algunas ideas?
Aquí hay un ejemplo mínimo que produce el primero:
\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}
Respuesta1
Aquí hay un intento con puntas de flecha.
(También tengo una solución con decoraciones, pero me confunden más que las puntas de las flechas).
Desafortunadamente, la Round Cap
punta de la flecha solo agrega (o elimina con la reversed
opción) un semicírculo desde el final de la línea. Esto funcionaría muy bien si el ancho de la línea fuera el doble del radio de un nodo circular.
El setup code
para la punta de la flecha Hug Cap
calculaalgo de matematicasy guarda tres valores:
- radio (esto se toma de la tecla de flecha
length
), - h, este es el recuadro (la altura), y
- un ángulo (después de todo, es un arco que se dibuja).
Existe la posibilidad de ampliar la definición de la punta de la flecha para incluir opciones como reversed
, open
, left
etc.
El deround
estilo calcula el radio a partir de nodos circulares. (Si bien esta respuesta está inspirada en el circle connection bar
estilo y la decoración de la mindmap
biblioteca, utiliza un enfoque diferente para extraer el radio de los nodos ya existentes).
Obviamente, los caminos deben ser ortogonales al borde de los círculos.
Esta solución debe usarse con los operadores to
/ edge
(usa \tikztostart
y \tikztotarget
para automatizar los cálculos de radios. No use otro line caps
que no sea butt
(el predeterminado), esto también se puede verificar dentro de la definición de la punta de la flecha.
Esto se rompe si el ancho de la línea es mayor que el diámetro y también para radios muy grandes (pero entonces, ¿por qué usar esto incluso?).
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}
Producción
Respuesta2
Encontré una manera, pero no parece ser la canónica, solo una forma que funciona: usar capas y luego aumentar la longitud de la línea:
\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 solución, basada en el comentario a continuación (use el centro como coordenada en lugar de líneas más largas)
\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}