3

I often get into the situation where I have to create something like this:

diagram

I managed to get this with this hacky (at least it seems hacky to me) code:

\documentclass{standalone}

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

\begin{document}

\begin{tikzpicture}[block/.style={draw, rectangle, minimum height=1cm}]
    \node (box) [block] {System};

    \node (in1)     [above left=-.5cm and 1.5cm of box]     {$\vec{u}_1$};
    \node (in2)     [below left=-.5cm and 1.5cm of box]     {$\vec{u}_2$};
    \node (out1)    [above right=-.5cm and 1.5cm of box]    {$\vec{v}_1$};
    \node (out2)    [below right=-.5cm and 1.5cm of box]    {$\vec{v}_2$};

    \draw [->] (in1) -- (box.west |- in1);
    \draw [->] (in2) -- (box.west |- in2);

    \draw [->] (box.east |- out1) -- (out1);
    \draw [->] (box.east |- out2) -- (out2);
\end{tikzpicture}

\end{document}

My question is: how could I do this better? What is the preferred way to create diagrams such as this? Can I do it without defining nodes for the input and output vectors separately and just doing something like

\draw [->] [above left=of box] {$\vec{u}_1$} -- (box);

Thank you for your help in advance!

  • You can check this answer to see how you can do it using pic with named ins and outs. – Kpym Oct 6 '18 at 6:03
3

Your code is already very clean. You may simplify things slightly by

  • using foreach to avoid unnecessary repetition,
  • putting all into one path (but there is not too much benefit from this except when you decide to give the thingy some universal features such as color or line thickness),
  • drop the unnecessary libraries (neither shapes nor arrows are needed here).

This leads to

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{positioning}

\begin{document}

\begin{tikzpicture}[block/.style={draw, rectangle, minimum height=1cm}]
    \node (box) [block] {System}
    node (in1)     [above left=-.5cm and 1.5cm of box]     {$\vec{u}_1$}
    node (in2)     [below left=-.5cm and 1.5cm of box]     {$\vec{u}_2$}
    node (out1)    [above right=-.5cm and 1.5cm of box]    {$\vec{v}_1$}
    node (out2)    [below right=-.5cm and 1.5cm of box]    {$\vec{v}_2$}
    foreach \X in {1,2}
    {(in\X) edge[->] (box.west |- in\X)
    (box.east |- out\X) edge[->] (out\X)};
\end{tikzpicture}

\end{document}

enter image description here

4

An option forced to use only one draw statement, nodes can be declared in the path; then using shape especific point like box.west, box.east and the most general way using box.angle, that find a point in the shape in the intersection of a line from the center of the shape and the shape, in this case at 25 degrees, to put the other text nodes I use coordinate shifting (coordinate)++(x_shift,y_shift) and declare a node in this point, finally to draw the arrows inside only one draw statement I use edge, I use the edge at the end because when you declare a node after the las coordinate of the edge, the node takes the first coordinate. I dont know if is the best way...

RESULT: The same as in your example but separated 1.5cm

MWE:

\documentclass[tikz,border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows,positioning}

\begin{document}

\begin{tikzpicture}[block/.style={draw, rectangle, minimum height=1cm}]
    \draw
    node (box)[block]{System}
    (box.180-25)++(-1.5,0) node{$\vec{u}_1$} edge[->] (box.180-25)
    (box.-180+25)++(-1.5,0) node{$\vec{u}_2$} edge[->] (box.-180+25)
    (box.25)++(1.5,0) node{$\vec{v}_1$} edge[<-] (box.25)
    (box.-25)++(1.5,0) node{$\vec{v}_2$} edge[<-] (box.-25)
    ;
\end{tikzpicture}

\end{document}
  • Thank you, I now realise that it would be a lot less clean this way :P – bertalanp99 Oct 5 '18 at 18:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.