7

Does Anyone Know How to Two Draw MIMO Blocks Connected Together? I am doing a project and need to draw a schematic that looks similar to the one below by using LATEX. Does anyone know how to do that? enter image description here In particular, I want to know how to put texts inside the block. I also want to know how to create these two blocks as well as how to connect them PROPERLY. The following is what I currently have. enter image description here

\documentclass{article}
\usepackage{amsfonts}
\usepackage{siunitx}
\usepackage[table]{xcolor}
\usepackage{booktabs}
\usepackage[margin=0.5in]{geometry}
\usepackage{tikz}
\usetikzlibrary{arrows, automata, backgrounds, fit, matrix, arrows.meta, calc, positioning}
\begin{document}
\begin{tikzpicture}[>=stealth]
\matrix[matrix of math nodes, nodes in empty cells, draw] (blockA) at (0,2)
{
A & & & F \\
B & & & G \\
C & & & H \\
D & & & I  \\
& & & & E \\
};
\matrix[matrix of math nodes,nodes in empty cells,draw,minimum width=30pt,below=of blockA] (blockB) 
{
A & & & F \\
B & & & G \\
C & & & H \\
D & & & I \\
E & & & J \\
};
\node at (blockB) {$Block B$};

\foreach \i in {1,2,3,4,5}
{
\draw[->] let \p1 = (blockA.west), \p2 = (blockA-\i-\i.west), \p3 = (blockB.west), \p4 = (blockB-\i-1.west) in (\x3,\y4) -| 
++(-2.4+0.2*\i,1) |- (\x1,\y2);
\draw[->] let \p1 = (blockA.east), \p2 = (blockA-\i-\i.east), \p3 = (blockB.east), \p4 = (blockB-\i-1.east) in (\x1,\y2) -|
++(1.6-0.2*\i,-1) |- (\x3,\y4);
}
\end{tikzpicture}
\end{document}
7

To make it symmetrical, I used absolute coordinates for the midpoint. The only tricky bit is finding a y value below the top block and above the bottom block.

Since there were a odd number of rows, I simply added the text as part of the matrix. If there were an even number, one could reserve the space using \hphantom{\text{Block A}} and overwrite the node as before.

\documentclass{article}
\usepackage{amsfonts}
\usepackage{siunitx}
\usepackage[table]{xcolor}
\usepackage{booktabs}
\usepackage[margin=0.5in]{geometry}
\usepackage{tikz}
\usetikzlibrary{arrows, automata, backgrounds, fit, matrix, arrows.meta, calc, positioning}
\begin{document}
\begin{tikzpicture}[>=stealth]
\matrix[matrix of math nodes, nodes in empty cells, draw] (blockA) at (0,2)
{
A & & F \\
B & & G \\
C & \text{Block A} & H \\
D & & I \\
E & & J \\
};
\matrix[matrix of math nodes,nodes in empty cells,draw,below=of blockA] (blockB) 
{
A & & F \\
B & & G \\
C & \text{Block B} & H \\
D & & I \\
E & & J \\
};

\foreach \i in {1,2,3,4,5}
{
\draw[->] let \p1 = (blockA.west), \p2 = (blockA-\i-1.west), \p3 = (blockB.west), \p4 = (blockB-\i-1.west) in (\x3,\y4) -| 
(-4+0.2*\i,0) |- (\x1,\y2);
\draw[->] let \p1 = (blockA.east), \p2 = (blockA-\i-1.east), \p3 = (blockB.east), \p4 = (blockB-\i-1.east) in (\x1,\y2) -|
(4-0.2*\i,0) |- (\x3,\y4);
}
\end{tikzpicture}
\end{document}

demo

  • Thank you so much. It works. Could you elaborate on what I should do if the number of rows is an even number. I don't really understand the sentence "If there were an even number, one could reserve the space using \hphantom{\text{Block A}} and overwrite the node as before." – LARRrrrY65464 Jul 9 '18 at 1:39
  • Never mind. I figured out what you mean. I wonder what if the number of arrows on the left is 4 for both blocks (i.e., the number of rows is also 4, that is, from A to D), and the number of arrows on the right side remains unchanged for both blocks. Could you show me the code for that if it is not too much trouble? – LARRrrrY65464 Jul 9 '18 at 1:58
  • The lines are generated using the foreach loop (which I personally regard as an unnecessary complication). The x values come from the edges of the block, but the y values come from the matrix entries (which are automatically assigned names like BlockA-1-1). – John Kormylo Jul 9 '18 at 13:58
2

Here is a solution that defines a new shape named block that can be used with an arbitrary number of in- and outputs. I made this once for a similar problem. Pros:

  • Arbitrary number of in- and outputs
  • Configurable space between in-/outputs
  • Tikz anchors at in-/outputs
  • Shape is the same as the default rectangle shape
  • flip option to have inputs on the right and outputs on the left

If you want, I could elaborate on the code, but you can also use it out of the box.

\documentclass[tikz]{standalone}

\usetikzlibrary{positioning}

\makeatletter
\newdimen\block@iospacing
\newdimen\block@height

\newif\if@block@flip

\tikzset{
    block/.code={
        \pgfkeys{
            /block/.cd,
            #1
        }
        \pgfmathsetlengthmacro{\block@height}{%
            max(10mm, int(max(\block@inputs,\block@outputs) * \block@iospacing))}
        \tikzset{
            draw,
            align=center,
            minimum width = 15mm,
            minimum height = \block@height,
            shape=block
        }
    }
}
\pgfkeys{
    /block/.is family,
    /block/.cd,
    inputs/.code={
        \pgfmathparse{int(#1)}
        \let\block@inputs=\pgfmathresult
    },
    inputs=1,
    outputs/.code={
        \pgfmathparse{int(#1)}
        \let\block@outputs=\pgfmathresult
    },
    outputs=1,
    io spacing/.code=\setlength\block@iospacing{#1},
    io spacing=5mm,
    flip/.is choice,
    flip/true/.code={\@block@fliptrue\def\@block@flipbool{1}},
    flip/false/.code={\@block@flipfalse\def\@block@flipbool{0}},
    flip/.default=true,
    flip=false,
}

\pgfdeclareshape{block}{
    \inheritsavedanchors[from={rectangle}]
    \savedanchor\centerpoint{%
        \pgf@x=.5\wd\pgfnodeparttextbox%
        \pgf@y=.5\ht\pgfnodeparttextbox%
        \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
    }
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{north west}
    \inheritanchor[from=rectangle]{north east}
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{text}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{mid}
    \inheritanchor[from=rectangle]{mid west}
    \inheritanchor[from=rectangle]{mid east}
    \inheritanchor[from=rectangle]{base}
    \inheritanchor[from=rectangle]{base west}
    \inheritanchor[from=rectangle]{base east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{south west}
    \inheritanchor[from=rectangle]{south east}
    \savedmacro\blockinputs{%
        \pgfmathparse{int(\block@inputs)}%
        \let\blockinputs=\pgfmathresult}%
    \savedmacro\blockoutputs{%
        \pgfmathparse{int(\block@outputs)}%
        \let\blockoutputs=\pgfmathresult}%
    \savedmacro\blockmaxio{%
        \pgfmathparse{int(max(\block@inputs,\block@outputs))}%
        \let\blockmaxio=\pgfmathresult}%
    \savedmacro\blockflip{%
        \pgfmathparse{\@block@flipbool}%
        \let\blockflip=\pgfmathresult}%
    \saveddimen\halfwidth{\pgfmathsetlength\pgf@x{%
            \pgfkeysvalueof{/pgf/minimum width}/2}\pgfmathresult}
    \saveddimen\halfheight{\pgfmathsetlength\pgf@x{%
            \pgfkeysvalueof{/pgf/minimum height}/2}\pgfmathresult}
    \saveddimen\iospacing{\pgfmathsetlength\pgf@x{%
            \block@iospacing}\pgfmathresult}
    \inheritbackgroundpath[from={rectangle}]
    \pgfutil@g@addto@macro\pgf@sh@s@block{%
        \pgfmathloop%
        \ifnum\pgfmathcounter>\blockinputs\relax%
        \else%
        \pgfutil@ifundefined{pgf@anchor@block@input \pgfmathcounter}{%
            \expandafter\xdef\csname pgf@anchor@block@input %
            \pgfmathcounter\endcsname{\noexpand%
                \pgf@sh@lib@block@in@anchor{\pgfmathcounter}%
            }%
        }{}
        \repeatpgfmathloop%
        \pgfmathloop%
        \ifnum\pgfmathcounter>\blockoutputs\relax%
        \else%
        \pgfutil@ifundefined{pgf@anchor@block@output \pgfmathcounter}{%
            \expandafter\xdef\csname pgf@anchor@block@output %
            \pgfmathcounter\endcsname{\noexpand%
                \pgf@sh@lib@block@out@anchor{\pgfmathcounter}%
            }%
        }{}
        \repeatpgfmathloop%
    }%
}

\def\pgf@sh@lib@block@in@anchor#1{%
    \pgf@process{\centerpoint}%
    \pgf@ya=\pgf@y%
    \ifnum\blockflip=0\relax%
        \pgf@process{\southwest}%
    \else%
        \pgf@process{\northeast}%
    \fi%
    \pgfmathsetlength\pgf@y{\pgf@ya + (0.5*(\blockinputs+1)-#1)*\iospacing}
}
\def\pgf@sh@lib@block@out@anchor#1{%
    \pgf@process{\centerpoint}%
    \pgf@ya=\pgf@y%
    \ifnum\blockflip=0\relax%
        \pgf@process{\northeast}%
    \else%
        \pgf@process{\southwest}%
    \fi%
    \pgfmathsetlength\pgf@y{\pgf@ya + (0.5*(\blockoutputs+1)-#1)*\iospacing}
}
\makeatother

\begin{document}
    \begin{tikzpicture}[block/.append style={minimum width=3cm},iolabel/.style={text width=2.5mm,align=center}]
        \node[block={inputs=4,outputs=5}](blockA){Block A};
        \node[block={inputs=5,outputs=4,flip,io spacing=8mm},below=of blockA](blockB){Block B};

        \foreach[count = \i] \letter in {F,...,J}{
            \node[left,iolabel] at (blockA.output \i) {\letter};
            \node[left,iolabel] at (blockB.input \i) {\letter};
            \draw[->] (blockA.output \i) -- ++(2-\i*0.2,0) |- (blockB.input \i);
        }
        \foreach[count = \i] \letter in {A,...,D}{
            \node[right,iolabel] at (blockA.input \i) {\letter};
            \node[right,iolabel] at (blockB.output \i) {\letter};
            \draw[->] (blockB.output \i) -- ++(-2+\i*0.2,0) |- (blockA.input \i);
        }
    \end{tikzpicture}
\end{document}

The result of this code is:

enter image description here

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.