6

I'd like to draw this very simple diagram below. No need those rounded corners on the feedback line.

desired

I tried to follow other guides, but I don't know how to draw the feedback line nor how to distribute the inputs vertically on the left side of the rectangle.

Below is my try:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{shapes,arrows,positioning}
\begin{document}

\tikzstyle{block} = [draw, rectangle, minimum height=3em, minimum width=3em]
\tikzstyle{virtual} = [coordinate]

\begin{tikzpicture}[auto, node distance=2cm]
    % Place nodes
    \node [virtual]                 (input)     {};
    \node [block, right of=input]   (model)     {Model};
    \node [virtual, right of=model] (output)    {};
    \node [virtual, below of=model] (feedback)  {};
    % Connect nodes
    \draw [->] (input) -- node {$u$} (model);
    \draw [->] (model) -- node [name=y] {$y$}(output);
    \draw [->] (y) |- (feedback);
\end{tikzpicture}

\end{document}

Rendering as follows:

enter image description here

Could you please guide me here? Thanks

5 Answers 5

10

To get the arrows coming in from the left to be as they are in the image, you can indicate the exact location with (model.N), where N is the number of degrees around the shape anti-clockwise starting from the east anchor. I.e., (model.90) would correspond to (model.north).

Rounded corners are obtained simply by adding rounded corners to \draw and starting your feedback line from (model) instead of (y).

You can also define the location of (input) with respect to the input position (here, model.165), and the node will be directly left of that point.

Lastly, I've set (feedback) to be below left of (model.west) in order to tighten up the loop a bit.

\documentclass[border=1mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows,positioning}
\begin{document}
\tikzstyle{block} = [draw, rectangle, minimum height=3em, minimum width=3em]
\tikzstyle{virtual} = [coordinate]
\begin{tikzpicture}[>=stealth,auto, node distance=2cm]
    % Place nodes
    \node [block] (model) {Model};
    \node [virtual, left=of model.165] (input)     {};
    \node [virtual, right=of model.0] (output)    {};
    \node [virtual, below left=of model.west] (feedback)  {};
    % Connect nodes
    \draw [->] (input) -- node {$u$} (model.165);
    \draw [->] (model) -- node [name=y] {$y$}(output);
    \draw [->,rounded corners] (model) -- (y.south) |- (feedback) |- (model.195);
\end{tikzpicture}
\end{document}

enter image description here

3
  • 1
    I'd personally rather use ($(model.north west)!.4!(model.south west)$) and ($(model.north west)!.6!(model.south west)$) instead of an angle, as if the node width changes you cannot guarantee the anchor position (as long as the model height is fixed). Or even ($model.west+(0,.2)$) and ($model.west+(0,-.2)$) if the height is changing...
    – s__C
    Apr 4, 2015 at 20:22
  • @s__C Good point. That works brilliantly for shapes with vertical sides, but the arrows would penetrate shapes like diamond.
    – erik
    Apr 5, 2015 at 18:04
  • @erik for a diamond I guess you have to modify to ($(model.west)!.4!(model.north)$) for example!
    – s__C
    Apr 6, 2015 at 7:47
4

Trying to reuse as much as possible of your original code, I did the two following changes:

  1. The "virtual" node feedback is now below left instead of below-
  2. I connected that virtual node with your model again, but used the syntax node.angle to specify the ending point, and the path |- to have the ortogonal lines.

So:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{shapes,arrows,positioning}
\begin{document}

\tikzstyle{block} = [draw, rectangle, minimum height=3em, minimum width=3em]
\tikzstyle{virtual} = [coordinate]

\begin{tikzpicture}[auto, node distance=2cm]
    % Place nodes
    \node [virtual]                 (input)     {};
    \node [block, right of=input]   (model)     {Model};
    \node [virtual, right of=model] (output)    {};
    \node [virtual, below left of=model] (feedback)  {};
    % Connect nodes
    \draw [->] (input) -- node {$u$} (model);
    \draw [->] (model) -- node [name=y] {$y$}(output);
    \draw [->] (y) |- (feedback) |- (model.200);
\end{tikzpicture}

\end{document}

Which produces:

Result

1
  • Thanks for you response. I'd definitely accept it if I could accept more than one. The only detail that made me opt for the other one was to having the input lines on the left vertically distributed. Anyway, your answers was enlightening as well!
    – POliveira
    Apr 3, 2015 at 23:11
1

As the following image shows, part of your problem is that your feedback node is probably not where you want it to be: it is far below your model.

enter image description here

This was produced with the following, of course you don't want the feed there it is just to show where your feedback node is. I have drawn your feedback loop using relative coordinates: ++(a,b) adds (a,b) to the last coordinate.

\documentclass[border=5mm,tikz]{standalone}
\usepackage{mwe}

\usepackage{tikz}
\usetikzlibrary{shapes,arrows,positioning}
\begin{document}

\tikzstyle{block} = [draw, rectangle, minimum height=3em, minimum width=3em]
\tikzstyle{virtual} = [coordinate]

\begin{tikzpicture}[auto, node distance=2cm]
    % Place nodes
    \node [virtual]                 (input)     {};
    \node [block, right of=input]   (model)     {Model};
    \node [virtual, right of=model] (output)    {};
    \node [below of=model] (feedback)  {feed};
    % Connect nodes
    \draw [->] (input) -- node {$u$} (model);
    \draw [->] (model) -- node [name=y] {$y$}(output);
    \draw [->,rounded corners] (y)--++(0,-1.5)--++(-2.5,0)--++(0,1.0)--++(0.6,0);
\end{tikzpicture}

\end{document}
0

I just made some blank nodes to draw the line to. Which works for a small diagram like this. The .center in the drawing of the lines makes the line go to the centre of the blank nodes so you don't get gaps in the line.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{shapes,arrows,positioning}
\begin{document}

\tikzstyle{block} = [draw, rectangle, minimum height=3em, minimum width=3em]
\tikzstyle{virtual} = [coordinate]

\begin{tikzpicture}[auto, node distance=2cm]
    % Place nodes
    \node [virtual]                 (input)     {};
    \node [block, right of=input]   (model)     {Model};
    \node [virtual, right of=model] (output)    {};
    \node [virtual, below of=model] (feedback)  {};
    \node at (0,-2) (invis) {};
    \node at (0,-0.35) (invis2) {};
    \node at (1.5,-0.35) (invis3) {};

    % Connect nodes
    \draw [->] (input) -- node {$u$} (model);
    \draw [->] (model) -- node [name=y] {$y$}(output);
    \draw [-] (y) |- (invis.center);
    \draw [-] (invis.center) -- (invis2.center);
    \draw [->] (invis2.center) -- (invis3);
\end{tikzpicture}

\end{document}

enter image description here

0

As a complement, here is a rudimentary way to do it with MetaPost. I call it rudimentary because, excepted for the cardinal points of the box which are given by the handy shortcuts from the boxes package (model.w, model.e, etc.) the connexions are “handmade”. The code of these connexions is thus relatively long, but it gives the opportunity to personnalise it at will. To be typeset with LuaLaTeX.

\documentclass[border=2mm]{standalone}
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
  input boxes;
  numeric h, v; h = .7cm; v = 1.25cm;

  primarydef p cornered c =
    (point 0 of p --
    for i=1 upto length(p) -1 :
      (point i   of p) shifted (c*(unitvector(point i-1 of p - point i   of p))) 
      .. controls point i of p ..
      (point i of p) shifted (c*(unitvector(point i+1   of p - point i of p)))
      --
    endfor point length(p) of p)
  enddef ;

  beginfig(1);
    boxit.model(btex Model etex);
    model.dy = 3.5mm;
    drawboxed(model); 

    pair A, B, C, D, E, F; 
    A = model.e; F = .5[model.w, model.sw];
    B = A + (h, 0); C = (xpart B, -v);
    D = (xpart F - 2h, -v);
    E = (xpart D, ypart F);
    drawarrow (A--B--C--D--E--F) cornered 3mm;
    drawarrow B - (3mm, 0) -- B + (1.25h, 0);
    label.top(btex $y$ etex, B);

    pair G, H; H = model.w; G = model.w - (2.5h, 0);
    drawarrow G -- H;
    label.top(btex $u$ etex, .5[G,H]);
  endfig;
\end{mplibcode}
\end{document}

Edit I have rounded the corners of the main connexion, thanks to a cornered operator. It has been taken from a macro of the same name available in the Metafun format of MetaPost and sligthly modified, since the original can be applied only on cycles.

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .