¿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:
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:
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 path
y 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”:
- el de fondo (
\tikz@figbox@bg
) - el camino real se dibuja
- 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 \pgfonlayer
tambié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 \setbox
que funcione como lo haría normalmente, dentro de esa macro que coloca el nodo en ese cuadro para la ruta.
La node on layer
clave simplemente hace que \tikz@setbox@which
sea global \setbox
y 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
main
capa no se puede elegir (es una especial que no se puede elegir con\pgfonlayer
ninguna de las dos).transform canvas
no funcionará (pero tampoco funciona conbehind 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
LC
con una transformación normal dentro de laLC'
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@whichbox
no 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 layer
no 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 forest
y 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
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}