TikZ:稳健且自动地创建信号流图(相变量形式)

TikZ:稳健且自动地创建信号流图(相变量形式)

采用这个答案,通过表示以下一组状态方程,创建了以下信号流图:

在此处输入图片描述

我想:

1-知道当节点数量及其连接信号不同时,如何优化和推广我的代码以使其更加稳健,而无需手动编辑它。

2-如果可能的话,使当前输出更清洁。

在此处输入图片描述

\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}

答案1

这篇文章不解决如何实现更好的布局的问题。目的是自动从矩阵生成图形。您可以通过以下方式定义矩阵

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

然后通过 foreach 循环创建图形。代码中有一些注释。也许最重要的新元素是pmark从矩阵条目获取标签的样式,即其参数是行和列索引,以及semicircle插入可用于边缘的半圆的样式。

\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}

在此处输入图片描述

相关内容