¿Cómo configurar el nodo en línea en una capa diferente a la línea?

¿Cómo configurar el nodo en línea en una capa diferente a la línea?

¿Es posible declarar que los nodos de las líneas están en la capa principal independientemente de que las líneas estén en la capa de fondo? Por ejemplo: ingrese la descripción de la imagen aquí

Con los siguientes MWE:

\documentclass[12pt,tikz,border=3mm]{standalone}
    \usetikzlibrary{arrows,arrows.meta,%
        backgrounds,positioning}
\pgfdeclarelayer{foreground} 
\pgfdeclarelayer{background}
   \pgfsetlayers{background,main,foreground}

    \usepackage{amsmath}
\begin{document}
    \begin{tikzpicture}[
    node distance = 0mm,
        LC/.style = {draw=#1,
            line width=1mm,
            arrows={-Stealth[fill=#1,inset=0pt,length=0pt 1.6,angle'=90]},
            },
         X/.style = {draw, very thin, fill=white, fill opacity=0.75,
            font=\scriptsize,
            text=black, text opacity=1, align=left,
            inner sep=2pt, sloped, anchor=west,pos=0.07},
                        ]\sffamily
%---
\linespread{0.8}
%-------
\coordinate                     (a0)    at (0,0);
\coordinate[right=77mm of a0]   (b0);
    \foreach \i [count=\xi from 0] in {1,2,...,4}
{
    \coordinate[below=7mm of a\xi]  (a\i);
    \coordinate[below=7mm of b\xi]  (b\i);
}
\draw[|->]  (a0) -- (a3) node[above left]   {$t$};
\draw[|->]  (b0) -- (b3) node[above right]  {$t$};
\draw[LC=gray]  (a1)
    to node[X] {data\\
                $(\text{SeqNum}=0,\ell=1000)$}
                (b2);
%-------
    \begin{scope}[ X/.append style={anchor=east},
                  LC/.append style={transform canvas={yshift=-2mm}},
                  on background layer]
\draw[LC=teal]  (b1)
    to node[X] {ACK(AckNum$=$1000)}
                (a2);
   \end{scope}
%----------------
    \end{tikzpicture}
        \end{document}

Yo obtengo:

ingrese la descripción de la imagen aquí

La primera imagen la obtengo dibujando la segunda línea dos veces: primero como línea y encima nuevamente una invisible con un nodo. Dado que mis diagramas reales tienen hasta una docena de líneas de este tipo, busco soluciones más convenientes para declarar que los nodos están en el plano principal incluso si la línea está en segundo plano.

Respuesta1

Juguemos con cajas.

En algún momento, TikZ presenta las clavesbehind pathy in front of path(para retroceder) que básicamente especifica uno u otro cuadro de ruta en el que se colocan los nodos. Cuando finalmente se dibuja el camino (dentro del ;final de los caminos), estos cuadros se “usan”:

  1. el de fondo ( \tikz@figbox@bg)
  2. el camino real se dibuja
  3. el de primer plano ( \tikz@figbox, que es el predeterminado para los nodos)

Cuando TikZ encuentra un nodo en el camino, en realidad no solosorteosél, dibuja el nodo en una de estas dos cajas.

Estas casillas se restablecen al inicio del camino. Estos cuadros son la razón por la que los nodos se colocan encima de sus rutas (aunque, para empezar, son sus propias rutas).


Con elcapas de PGF, sucede algo muy similar pero en lugar de solo un nodo, todo lo que esté entre \begin{pgfonlayer}y \end{pgfonlayer}se colocará dentro de ese cuadro.

Al final de la imagen estas cajas se “usan”. (Hay algunas tareas domésticas adicionales que creo que son para anidar fotografías).

Ahora, en lugar de colocar el nodo en el cuadro que utiliza TikZ en el, ;podemosintentarpara colocarlo directamente sobre una de las capas.

Dado que esto sucede en algún lugar profundo de algunos grupos, esto debe ser global (y de hecho \pgfonlayertambién lo es, ya que se puede usar dentro de un alcance en algún lugar, y de hecho lo será cuando se use on background layer).


Para implementar esto, cambio uno \setbox(afortunadamente el primero) por uno personalizado \tikz@setbox@which, que se permite para \setboxque funcione como lo haría normalmente, dentro de esa macro que coloca el nodo en ese cuadro para la ruta.

La node on layerclave simplemente hace que \tikz@setbox@whichsea global \setboxy que el cuadro sea una de las capas y no uno de los cuadros de ruta.

Ahora puedes decir

\begin{scope}[
  X/.append style={anchor=east},
  LC'/.style={yshift=-2mm}, % no transform canvas
  on background layer]
\draw[LC=teal] ([LC'] b1) % ........ ←
  to node[X, node on layer=foreground] {ACK(AckNum$=$1000)} ([LC'] a2);
\end{scope}

Y esto ya muestra lo que no funciona con esto:

  • La maincapa no se puede elegir (es una especial que no se puede elegir con \pgfonlayerninguna de las dos).

  • transform canvasno funcionará (pero tampoco funciona con behind path). Puede haber formas de evitarlo, pero el manual recomienda:

    En resumen, no deberías utilizar transformaciones de lienzo a menos que realmente sepas lo que estás haciendo.

    y agregaré… a menos que realmente lo necesites.

    Reemplacé tu adición LCcon una transformación normal dentro de la LC'clave que se agrega manualmente a cada coordenada. (Me gustaría que hubiera alguna forma de “desarreglar” las coordenadas/nodos para que actúen como coordenadas normales y las transformaciones también se apliquen a ellos, pero incluso el manual solo ofreceuna solución @-montada.)

Además, no lo use con nada más que nodos. La macro "decisiva" \tikz@whichboxno solo se usa para nodos sino también para bordes, marcas de trazado, matrices, nodos secundarios (no es lo mismo que nodos simples) e imágenes. Usarlo \node on layerno funcionará; en el mejor de los casos, los bordes, las marcas de la trama, la matriz, los elementos secundarios y las imágenes simplemente no aparecerán. (De todos modos, la adición al cuadro se olvida después de la ruta actual). Se deben realizar más parches para eso.


Dicho esto, también puede simplemente colocar un nodo/coordenada vacío a lo largo de la ruta (para guardar la posición y la rotación) y luego hacer referencia a eso al colocar el nodo real al final de todo el dibujo lineal. Sin embargo, será necesario un buen mantenimiento para que sea fácil de usar.

Y luego está todoPosicionamiento de nodo diferidodonde primero "haces" un nodo pero lo colocas más tarde (utilizado por foresty la biblioteca de dibujo de gráficos). Sin embargo, eso tampoco es muy sencillo. (¡Más cajas!)

Código

\documentclass[12pt, tikz, border=3mm]{standalone}
\usetikzlibrary{arrows, arrows.meta, backgrounds, positioning}
\pgfdeclarelayer{foreground}\pgfdeclarelayer{background}
\pgfsetlayers{background,main,foreground}
\makeatletter\ExplSyntaxOn % replace only first one
\tl_replace_once:Nnn \tikz@fig@continue { \setbox } { \tikz@setbox@which }
\ExplSyntaxOff
\let\tikz@setbox@which\setbox
\tikzset{node on layer/.code={%
  \expandafter\def\expandafter\tikz@whichbox\expandafter
    {\csname pgf@layerbox@#1\endcsname}%
  \def\tikz@setbox@which{\global\setbox}}}
\makeatother
\usepackage{amsmath}
\begin{document}
\begin{tikzpicture}[
  node distance = 0mm,
  LC/.style = {draw=#1, line width=1mm,
    arrows={-Stealth[fill=#1,inset=0pt,length=0pt 1.6,angle'=90]}},
  X/.style = {draw, very thin, fill=white, fill opacity=0.75,
    font=\scriptsize, text=black, text opacity=1, align=left,
   inner sep=2pt, sloped, anchor=west,pos=0.07}]
\sffamily\linespread{0.8}

\coordinate                     (a0)    at (0,0);
\coordinate[right=77mm of a0]   (b0);
\foreach \i [count=\xi from 0] in {1,2,...,4}
  \coordinate[below=7mm of a\xi]  (a\i)
   coordinate[below=7mm of b\xi]  (b\i);
\draw[|->] (a0) -- (a3) node[above left]   {$t$};
\draw[|->] (b0) -- (b3) node[above right]  {$t$};
\draw[LC=gray] (a1) to node[X] {data\\$(\text{SeqNum}=0,\ell=1000)$} (b2);

\begin{scope}[
  X/.append style={anchor=east},
  LC'/.style={yshift=-2mm}, % no transform canvas
  on background layer]
\draw[LC=teal] ([LC'] b1)
  to node[X, node on layer=foreground] {ACK(AckNum$=$1000)} ([LC'] a2);
\end{scope}
\end{tikzpicture}
\end{document}

Producción

ingrese la descripción de la imagen aquí

Respuesta2

¿Qué tal colocar el nodo en la capa frontal con un comando de ruta de seguimiento?

\path (b1) to node[X,anchor=east,yshift=-2mm] {ACK(AckNum$=$1000)} (a2);

Aquí está el documento completo:

\documentclass[12pt,tikz,border=3mm]{standalone}
\usetikzlibrary{arrows,arrows.meta,backgrounds,positioning}
\pgfdeclarelayer{foreground} 
\pgfdeclarelayer{background}
\pgfsetlayers{background,main,foreground}
\usepackage{amsmath}

\begin{document}

\begin{tikzpicture}
  [
    node distance = 0mm,
    LC/.style = {draw=#1,
                 line width=1mm,
                 arrows={-Stealth[fill=#1,inset=0pt,length=0pt 1.6,angle'=90]},
                },
    X/.style = {draw, 
                very thin, 
                fill=white, 
                fill opacity=0.75,
                font=\scriptsize,
                text=black, 
                text opacity=1, 
                align=left,
                inner sep=2pt, 
                sloped, 
                anchor=west,
                pos=0.07},
  ]
 \sffamily
%---
  \linespread{0.8}
%-------
  \coordinate                     (a0)    at (0,0);
  \coordinate[right=77mm of a0]   (b0);
  \foreach \i [count=\xi from 0] in {1,2,...,4}
    {
      \coordinate[below=7mm of a\xi]  (a\i);
      \coordinate[below=7mm of b\xi]  (b\i);
    } 
  \draw[|->]  (a0) -- (a3) node[above left]   {$t$};
  \draw[|->]  (b0) -- (b3) node[above right]  {$t$};
  \draw[LC=gray]  (a1)
                  to 
                  node[X] {data\\
                  $(\text{SeqNum}=0,\ell=1000)$}
                  (b2);
%-------
  \begin{scope}[X/.append style={anchor=east},
                LC/.append style={transform canvas={yshift=-2mm}},
                on background layer]
    \draw[LC=teal]  (b1)
                    to 
                    (a2);
 \end{scope}
%----------------
  \path (b1) to node[X,anchor=east,yshift=-2mm] {ACK(AckNum$=$1000)} (a2);
\end{tikzpicture}
\end{document}

ingrese la descripción de la imagen aquí

información relacionada