Desenhando um diagrama de blocos com TiKz

Desenhando um diagrama de blocos com TiKz

Preciso de ajuda para desenhar um diagrama de blocos usando TiKz.

Quero desenhar algo parecido com isto:

insira a descrição da imagem aqui

No entanto, estou lutando para ir além disso até agora:

insira a descrição da imagem aqui

usando o código abaixo:

\documentclass{standalone}

\usepackage{tikz}       
\usetikzlibrary{arrows,positioning,patterns,decorations.pathmorphing}

\begin{document}

\tikzstyle{block} = [draw, rectangle, minimum size=5em]
\tikzstyle{joint} = [draw, circle, minimum size=1em]

\begin{tikzpicture}[>=stealth, auto, node distance=2cm]
    % Place nodes
    \node [block] (system) {System};
    \node [coordinate, left=of system] (infork) {};
    \node [coordinate, left=of infork] (input) {};
    \node [coordinate, right=of system] (outfork) {};
    \node [coordinate, right=of outfork] (output) {};
    \node [coordinate, above=of system] (disturbances) {};
    \node [block, below=of system] (model) {Model};
    \node [joint, right=of model] (sum) {};
    \node [coordinate, right=of sum] (error) {};
    % Connect nodes
    \draw [->, decorate, decoration={snake, post length=1mm}] (disturbances) -- node {\(d'\)} (system);
    \draw [->] (input) -- node {\(u'\)} (system);
    \draw [->] (system) -- node {\(t'\)} (output);
    \draw [->] (model) -- node {\(y\)} (sum);
    \draw [->] (sum) -- node {\(\epsilon\)} (error);
    \draw [->] (infork) |- node {\(u\)} (model);
    \draw [->] (outfork) -- node {\(t\)} (sum);
\end{tikzpicture}

\end{document}

Ou seja, gostaria de descobrir como:

  • Coloque o retângulo chamado Measuremententre os dois blocos. Preferencialmente, este retângulo seria preenchido com a cor cinza claro e seria delimitado por uma linha tracejada. Nota: não me importo que o retângulo cubra as linhas verticais. Eu só quero que eles mantenham sua direção vertical

  • Coloque o sumcírculo exatamente atrás do garfo para ter uma linha vertical conectando-se t'a este círculo

  • Coloque os ue tcorretamente (por exemplo, como estão na primeira foto)

  • Tenha os sinais +e -onde as setas encontram o círculo

Responder1

Nenhuma das respostas aqui captura a aparência desenhada à mão do original. Aqui está uma solução Metapost que usaesboço mppara obter a aparência desenhada à mão. Também uso as fontes Comic Neue e Euler. Aqui está o resultado:

insira a descrição da imagem aqui

    \usetypescriptfile[euler]
\definetypeface[mainfont][rm][specserif][ComicNeue][default]
\definetypeface[mainfont][mm][math] [pagellaovereuler][default]
\setupbodyfont[mainfont,12pt]

% Set upright style for Euler Math
\appendtoks \rm \to \everymathematics
\setupmathematics
  [lcgreek=normal, ucgreek=normal]

\startMPinclusions
  input rboxes;
  input mp-sketch;
\stopMPinclusions

\defineframed
  [labelframe]
  [
    background=color,
    backgroundcolor=gray,
    frame=off,
  ]

\starttext
\startMPpage[offset=3mm]
  sketchypaths;

  defaultdx := 16bp;
  defaultdy := 16bp;
  circmargin := 5bp;
  sketch_amount := 2bp;

  u := 1cm;
  drawoptions(withpen pencircle scaled 1bp);

  boxit.system("SYSTEM");
  boxit.model ("MODEL");
  circleit.adder("$\cdot$");

  system.c = origin;
  system.s - model.n = (0, 3u);

  z.0 = system.w - (2u, 0);
  z.1 = 0.5[  z.0, system.w ];
  z.2 = (x.1, ypart model.w);
  z.3 = system.e + (u, 0);
  z.4 = system.e + (2u, 0);
  z.5 = (x.4, y.2);

  adder.c = (x.3, ypart model.c);

  drawboxed(system, model, adder);

  z.6 = 0.5[system.s, model.n];
  stripe_path_n
    (withpen pencircle scaled 2 withcolor 0.5white)
    (draw)
    fullsquare xyscaled(x.3 - x.1 + u, 2*LineHeight) 
    shifted z.6 dashed evenly;

  label("\labelframe{Measurement}", z.6);


  % Reduce the amount of randomness for the lines
  sketch_amount := bp;

  drawarrow z.0 -- lft system.w;
  drawarrow z.1 -- z.2 -- lft model.w;
  drawarrow system.e -- z.4 ;
  drawarrow model.e -- lft adder.w ;
  drawarrow z.3 -- top adder.n ;
  drawarrow adder.e -- z.5 ;

  label.urt("$-$", adder.n);
  label.llft("$+$", adder.w);

  label.top("$u'$", z.1);
  label.top("$t'$", z.3);
  label.top("$ε$", 0.5[adder.e, z.5]);

  dx := 12bp;
  label.urt("$t$", adder.n + (0, dx));
  label.urt("$u$", z.2 + (0, dx));

\stopMPpage
\stoptext

Responder2

Era isso que você estava procurando?

Conserta:

  1. Adicionado um nó Measurementposicionando-o no meio do caminho entre os nós Systeme Modelusando esta sintaxe: \node ... at ($(system)!.5!(model)$) {};. Isso requer calcser adicionado às bibliotecas Tikz.
  2. Alterou seu caminho diagonal \draw [->] (outfork) -| (sum.north) node [very near end] {\(t\)};para que o nó pare exatamente no ponto norte da soma.
  3. O [very near end]acima garante que o nó apareça muito próximo da ponta da seta.
  4. Removido minimal sizeseus nós que os fazem parecer quadrados (é um pouco feio) e substituído por inner sepque adiciona espaço dentro do nó de forma consistente para que as bordas do retângulo fiquem igualmente distantes do texto do nó.
  5. Para o nó u(o caminho à esquerda), adicionei a chave [anchor=south west]para que ele se mova um pouco para a direita e para cima e apareça próximo ao caminho.
  6. Etiquetas usadas para os símbolos -e +. Originalmente eles eram nós, mas fica melhor assim e o código é mais limpo e curto.

figura 1

\documentclass{standalone}

\usepackage{tikz}       
\usetikzlibrary{arrows,positioning,patterns,decorations.pathmorphing,calc}

\begin{document}

\tikzstyle{block} = [draw, rectangle, inner sep=6pt]
\tikzstyle{joint} = [draw, circle,minimum size=1em]

\begin{tikzpicture}[>=stealth, auto, node distance=2cm]
    % Place nodes
    \node [block] (system) {System};
    \node [coordinate, left=of system] (infork) {};
    \node [coordinate, left=of infork] (input) {};
    \node [coordinate, right=of system] (outfork) {};
    \node [coordinate, right=of outfork] (output) {};
    \node [coordinate, above=of system] (disturbances) {};
    \node [block, below=of system] (model) {Model};
    \node [joint, right=of model, anchor=center,label={[shift={(2mm,-1mm)}]-},label={[shift={(-3mm,-5.5mm)}]\tiny +}] (sum) {};

    \node [coordinate, right=of sum] (error) {};
    \node [block, dashed, fill=gray, anchor=center, text width=7cm, align=center] at ($(system)!.5!(model)$) {\textsc{Measurement}};

    % Connect nodes
    \draw [->, decorate, decoration={snake, post length=1mm}] (disturbances) -- node {\(d'\)} (system);
    \draw [->] (input) -- node {\(u'\)} (system);
    \draw [->] (system) -- node {\(t'\)} (output);
    \draw [->] (model) -- node {\(y\)} (sum);
    \draw [->] (sum) -- node {\(\epsilon\)} (error);
    \draw [->] (infork) |- node [anchor=south west] {\(u\)} (model);
    \draw [->] (outfork) -| (sum.north) node [very near end] {\(t\)};
\end{tikzpicture}

\end{document}

Responder3

Para quem possa interessar, aqui está uma solução comMetaPoste aMetaObjpacote, dentro de um programa LuaLaTeX. Baseia-se nos parâmetros se mque permitem localizar as caixas “Sistema” e “Modelo”, respectivamente centradas nos pontos (s,0)e (s, m).

\documentclass[border=2mm]{standalone}
\usepackage{luamplib}
  \mplibtextextlabel{enable}
\begin{document}
  \begin{mplibcode}
    input metaobj
    s := 4.5cm; m := -3cm; % locates upper and lower boxes
    beginfig(1);
      % Central box
      newBox.msrmt("Measurement") "filled(true)", "fillcolor(.8white)", 
        "dx(.6s)", "framestyle(dashed evenly)";
      msrmt.c = (s, .5m); drawObj(msrmt);
      % Upper and lower boxes
      newBox.syst("System") "dx(2mm)", "dy(3mm)"; 
      newBox.model("Model") "dx(2mm)", "dy(3mm)";
      syst.c = (s, 0); model.c = (s, m);
      drawObj(syst); drawBox(model);
      % Empty circle
      ep := .5(xpart syst.w); t := xpart syst.e + ep; u := xpart syst.w - ep;
      newCircle.circ("") "circmargin(1.5mm)";
      circ.c = (t, m);
      drawObj(circ);
      % Connections
      drawarrow origin -- syst.w;
      drawarrow (u, 0) -- (u, m) -- model.w;
      drawarrow syst.e -- (t+ep, 0);
      drawarrow (t, 0) -- circ.n;
      drawarrow model.e -- circ.w;
      drawarrow circ.e -- (t+ep, m);
      % The spring (and its label)
      newEmptyBox.upper(0, 0); upper.c = (s, -.75m);
      picture lab; lab = textext("$d'$");
      nczigzag(upper)(syst) "coilwidth(2.5mm)", "coilarmA(0mm)", 
        "coilarmB(3mm)", "linearc(.4mm)", "labpic(lab)", "labdir(rt)";
      % Other labels  
      label.top("$u'$", (u, 0)); label.urt("$u$", (u, m));
      label.top("$t'$", (t, 0));
      label.top("$y$", .5(model.e+circ.w));
      label.rt("$t$", (t, ypart(.5(msrmt.s+circ.n))));
      label.top("$\epsilon$", .5[(t,m), (t+ep, m)]);
      labeloffset := .5bp;
      label.llft("\tiny$+$", circ.sw);
      label.urt("\tiny$-$", circ.ne);
      labeloffset := 3bp;
    endfig; 
  \end{mplibcode}
\end{document}

insira a descrição da imagem aqui

Responder4

Obrigado, acabei misturando as respostas de Ignasi e Alenanno da seguinte forma:

\documentclass{standalone}

\usepackage{tikz}       
\usetikzlibrary{arrows, positioning, patterns, calc, decorations.pathmorphing}

\begin{document}

\tikzstyle{block} = [draw, rectangle, inner sep=6pt, minimum width=2cm, minimum height=1cm, align=center]
\tikzstyle{joint} = [draw, circle, minimum size=1em, anchor=center]
\tikzstyle{layer} = [draw, rectangle, dashed, fill=gray!20, minimum width=7cm, minimum height=8mm, align=center, anchor=center]

\begin{tikzpicture}[>=stealth, auto, node distance=2cm]
    % Place nodes
    \node [block] (system) {System};
    \node [block, below=of system] (model) {Model};
    \node [layer] at ($(system)!.5!(model)$) {\textsc{Measurement}};
    \coordinate [left=of system] (infork) {};
    \coordinate [left=of infork] (input) {};
    \coordinate [right=of system] (outfork) {};
    \coordinate [right=of outfork] (output) {};
    \coordinate [above=of system] (disturbances) {};
    \node [joint, label={[inner sep=1pt]210:\tiny\(+\)}, label={[inner sep=1pt]60:\tiny\(-\)}] (sum) at (outfork|-model) {};
    \coordinate (error) at (output|-model) {};
    % Connect nodes
    \draw [->, decorate, decoration={snake, post length=1mm}] (disturbances) -- node {\(d'\)} (system);
    \draw [->] (input) -- node {\(u'\)} (system);
    \draw [->] (system) -- node {\(t'\)} (output);
    \draw [->] (model) -- node {\(y\)} (sum);
    \draw [->] (sum) -- node {\(\epsilon\)} (error);
    \draw [->] (infork) |- node [anchor=south west] {\(u\)} (model);
    \draw [->] (outfork) -| (sum.north) node [very near end] {\(t\)};
\end{tikzpicture}

\end{document}

obtendo o próximo diagrama (ignore todo o quadro ao redor):

insira a descrição da imagem aqui

  1. Segui a sugestão de Ignasi de usar \coordinateem vez de \node [coordinate].

  2. Também usei |-e -|para melhor alinhamento, como sugeriu Ignasi. Aliás, foi por esse motivo que acabei não aceitando a solução de Alenanno, pois o Measurementsbloco não estava perfeitamente alinhado ao centro e o garfo de saída não estava exatamente acima do sumnó. (Não tenho certeza se é visível a sobreposição da borda na imagem abaixo)

insira a descrição da imagem aqui

  1. Usei a referência de ângulo para posicionar os sinais +e -assim como Ignasi fez, porém encurtei um pouco a fonte, como fez Alenanno.

  2. Para o Measurementsbloqueio, posicionamento, segui a abordagem do Alenanno. Esta parte foi a que me impediu de aceitar a solução do Ignasi, pois procurava um Measurementsbloco que ultrapassasse as linhas verticais como na imagem feita à mão acima. Hackeando um pouco o código do Alenanno, acabei de criar um novo estilo de bloco.

  3. Além disso, as dicas do Alenanno sobre as opções very near ende anchor=south westforam extremamente úteis! (e este foi outro detalhe onde a solução de Ignasi não foi 100% satisfatória).

Obrigado novamente a ambos. Eu não tinha certeza de qual resposta aceitar porque ambas foram muito úteis, mas decidi misturá-las e apresentar a solução que acabei usando, na esperança de ajudar outra pessoa.

informação relacionada