TikZ: creación robusta y automatizada de un gráfico de flujo de señales (forma de fase variable)

TikZ: creación robusta y automatizada de un gráfico de flujo de señales (forma de fase variable)

Adoptandoesta respuesta, se ha creado el siguiente diagrama de flujo de señales representando el siguiente conjunto de ecuaciones de estado:

ingrese la descripción de la imagen aquí

Me gustaría:

1- saber cómo se puede optimizar y generalizar mi código para que sea más robusto cuando la cantidad de nodos y sus señales de conexión difieren sin tener que editarlo manualmente.

2- haga que la salida actual sea más limpia si es posible.

ingrese la descripción de la imagen aquí

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings,positioning,arrows.meta}
\newif\iflabrev
\begin{document}
    \begin{tikzpicture}
        [
        relative = false,
        node distance = 15 mm,
        label revd/.is if=labrev,
        %label revd/.default=true,
        amark/.style = {
            decoration={             
                markings,   
                mark=at position {0.5} with { 
                    \arrow{stealth},
                    \iflabrev \node[below] {#1};\else \node[above] {#1};\fi
                }
            },
            postaction={decorate}
        },
        terminal/.style 2 args={draw,circle,inner sep=2pt,label={#1:#2}},
        ]
        %
        %Place the nodes
        \node[terminal={left}{$R(S)$}] (a) at (0,0) {};
        \node[terminal={below right}{$sX_3(s)$}] (b) [right=of a] {};
        \node[terminal={below right}{$X_3(S)$}] (c) [right=of b] {};
        \node[terminal={[xshift=-4mm]below right}{$sX_2(s)$}] (d) [right=of c] {};
        \node[terminal={[xshift=-4mm]below right}{$X_2(s)$}] (e) [right=of d] {};
        \node[terminal={[xshift=-4mm]below right}{$sX_1(s)$}] (f) [right=of e] {};
        \node[terminal={[xshift=-4mm]below right}{$X_1(s)$}] (g) [right=of f] {};
        \node[terminal={right}{$Y(s)$}] (h) [right=of g] {};
        %
        %Draw the connections
        \foreach \target/\bend/\text/\loose in {b/0/7/0, d/90/5/1.5, f/90/2/1.5}
        \draw[amark=\text] (a) to[bend left=\bend,looseness=\loose] (\target);
        
        \draw[amark=1/s] (b) to (c);
        \foreach \source/\text/\loose in {c/-4/2, e/-3/1.5, g/1/1.5}
        \draw[amark=\text] (\source) to[bend left=90, looseness=\loose] (b);
        
        \foreach \target/\text/\loose in { d/-6/1.5, f/2/2}
        \draw[amark=\text] (g) to[bend left=90, looseness=\loose] (\target);
        
        \foreach \source/\text in {c/9, e/6}
        \draw[amark=\text] (\source) to[bend left=90, looseness=1.5] (h);
        
        \draw[amark=2] (c) to (d);
        \draw[amark=3] (c) to[bend right=90, looseness=1.5] (f);
        \draw[amark=1/s] (d) to (e);
        \draw[amark=-5] (e) to (f);
        \draw[amark=-2,label revd] (e) to[bend left=90, looseness=2] (d);
        \draw[amark=1/s] (f) to (g);
        \draw[amark=-4] (g) to (h);
    \end{tikzpicture}
\end{document}

Respuesta1

Esta publicación no aborda la cuestión de lograr un mejor diseño. El propósito es generar el gráfico a partir de una matriz automáticamente. Puede definir una matriz mediante

\edef\mmat{{2,-5,3,2},{-6,-2,2,5},{1,-3,-4,7},{-4,6,9,0}}

y luego el gráfico se crea mediante bucles foreach. Hay algunas anotaciones en el código. Los nuevos ingredientes quizás más importantes son el pmarkestilo que obtiene las etiquetas de las entradas de la matriz, es decir, sus argumentos son el índice de fila y columna, y el semicircleestilo que inserta un semicírculo que puede usarse en los bordes.

\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{calc,decorations.markings,positioning,arrows.meta}
\newif\iflabrev
\begin{document}
    \begin{tikzpicture}[node distance = 15 mm,
        label revd/.is if=labrev,
        label revd/.default=true,
        amark/.style = {
            decoration={             
                markings,   
                mark=at position {0.5} with { 
                    \arrow{stealth},
                    \iflabrev \node[below] {#1};\else \node[above] {#1};\fi
                }
            },
            postaction={decorate}
        }, % make the mark an entry of the \mmat matrix
        pmark/.style n args={2}{amark={$%
            \pgfmathparse{int({\mmat}[\numexpr#1][\numexpr#2])}%
                \pgfmathresult$}},
        terminal/.style 2 args={draw,alias=ln,circle,inner sep=2pt,label={#1:#2}},
        % semicircle path
        semicircle/.style={to path={let \p1=($(\tikztotarget)-(\tikztostart)$)
            in \ifdim\x1>0pt
              (\tikztostart.north) arc[start angle=180,end angle=0,radius=0.5*\x1]
            \else
              (\tikztostart.south) arc[start angle=0,end angle=-180,radius=-0.5*\x1]
            \fi}}
        ]
        % define the  matrix 
        \edef\mmat{{2,-5,3,2},{-6,-2,2,5},{1,-3,-4,7},{-4,6,9,0}}
        \pgfmathtruncatemacro{\dimy}{dim({\mmat})} % number of rows
        \pgfmathtruncatemacro{\dimx}{dim({\mmat}[0])} % number of columns
        % create the graph
        \path % R node
        node[terminal={left}{$R(S)$},alias={X-\dimy}] (R) {}
        % loop over matrix entries
        foreach \Y [evaluate=\Y as \X using {int(\dimy-\Y)}]
        in {1,...,\numexpr\dimy-1}
        {node[right=of ln,terminal={below right}{% sX_i node
            $sX_{\X}(s)$}](sX-\X){}
        node[right=of ln,terminal={below right}{% X_i node
            $X_{\X}(s)$}](X-\X){}
        % ege from sX_i to X_i  
        (sX-\X) edge[amark={$\frac{1}{s}$}] (X-\X)
        % edge from X_{i+1} to X_i  (R had an alias)
        (X-\the\numexpr\X+1) edge[pmark={\X-1}{\X}] (sX-\X)
        % semicircle edge from X_i to sX_i
        (X-\X) edge[semicircle,label revd,pmark={\X-1}{\X-1}] (sX-\X)
        % various semicircles
        \ifnum\Y>1
         (R) edge[semicircle,pmark={\X-1}{\dimx-1}] (sX-\X) 
         foreach \Z in {1,...,\numexpr\Y-1} {
          (X-\X) edge[semicircle,pmark={\X+\Z-1}{\X-1}] (sX-\the\numexpr\X+\Z)
         }
        \fi
        }% the Y node
        node[right=of ln,terminal={right}{$Y(s)$}](Y){}
        (X-1) edge[pmark={\dimy-1}{0}] (Y)
        % semicircles goint to Y
        foreach \Y [evaluate=\Y as \X using {int(\dimy-\Y)}]
         in {1,...,\numexpr\dimy-2}
        {(X-\X) edge[semicircle,pmark={\dimy-1}{\X-1}] (Y)};
    \end{tikzpicture}
\end{document}

ingrese la descripción de la imagen aquí

información relacionada