Mejor ajuste de línea al nodo en TiKZ

Mejor ajuste de línea al nodo en TiKZ

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:

ingrese la descripción de la imagen aquí

me gustaria tener esto

ingrese la descripción de la imagen aquí

¿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 Cappunta de la flecha solo agrega (o elimina con la reversedopció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 codepara la punta de la flecha Hug Capcalculaalgo 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, leftetc.

El deroundestilo calcula el radio a partir de nodos circulares. (Si bien esta respuesta está inspirada en el circle connection barestilo y la decoración de la mindmapbiblioteca, 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 \tikztostarty \tikztotargetpara automatizar los cálculos de radios. No use otro line capsque 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

ingrese la descripción de la imagen aquí

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}

Resultado

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}

información relacionada