I have a diagram where layers of blocks are stacked on top of each other as shown in the image.

enter image description here

Using this code:

\usetikzlibrary{shapes.geometric, arrows, chains, calc}

\begin{tikzpicture}[start chain=1 going right, start chain=2 going below, node distance=1mm]
        vert/.style  = {draw, rectangle, minimum width=1.9cm, minimum height=1cm, text centered, text width=1.2cm, font=\scriptsize, draw=black, fill=none},
        mid/.style   = {draw, rectangle, minimum width=8cm+3\pgflinewidth, minimum height=1cm, text centered, text width=8.0cm, font=\scriptsize, draw=black, fill=none},
        infra/.style = {draw, rectangle, minimum width=8cm+3\pgflinewidth, minimum height=1cm, text centered, text width=8.0cm, font=\scriptsize, draw=black, fill=none}
    \node [name=r1c1, on chain=1, vert] {A};
    \node [name=r1c2, on chain=1, vert] {B};
    \node [name=r1c3, on chain=1, vert] {...};
    \node [name=r1c4, on chain=1, vert] {X};
    \draw let \p1=($(r1c4.east)-(r1c1.west)$), \n1 = {veclen(\x1,\y1)} in node [name=r3c1, on chain=2, mid, anchor=north west, yshift=-1mm, minimum width=\n1-\pgflinewidth] at (r1c1.south west) {Middle};
    \draw let \p1=($(r1c4.east)-(r1c1.west)$), \n1 = {veclen(\x1,\y1)} in node [name=r4c1, on chain=2, infra, minimum width=\n1-\pgflinewidth] {Bottom};

Now I want to add another layer of four blocks (e.g. 1, 2, ..., N) at the top, each with the same width as A, B, ..., X. And for each (vertical) pair, e.g. 1 and A, draw a dashed rectangle to enclose them, and evenly distribute the four pairs (each pair consists of two blocks vertically and the dashed enclosing block) across the width of Middle/Bottom layers. Finally, draw a double-headed arrow vertically to the right of the whole stack diagram, with texts Up and Down at either end of the arrow respectively.

Excuse for my bad drawing, but hopefully the image below illustrates what I want

enter image description here

I fiddled with the chains package but struggle to add another four blocks to the top. Any suggestion would be appreciated

  • 2
    a sketch what you like to have would be of big help. from your description i understand only that you like to draw around some nodes a node with dashed lines ... (for this the library fit is very handy). – Zarko Jan 9 '19 at 7:00
  • @Zarko thanks for the suggestion. I've added a drawing to show what I have in mind – MLister Jan 9 '19 at 8:06
  • now is more clear. i have prepared half of answer, for finishing i need to wait that some maintaines work on PC will be finished. – Zarko Jan 9 '19 at 8:27
  • i succeed to upload my answer. – Zarko Jan 9 '19 at 8:58

as starting point:

edit (2)

adoption to beamer document class, this time tested twice that code is right one ...

\usetikzlibrary{arrows.meta, calc, chains, fit}

\begin{frame}[fragile]  % <---
node distance = 2mm,
  start chain = going right,
   box/.style = {draw, minimum width=#1, minimum height=1cm,
                 text width =\pgfkeysvalueof{/pgf/minimum width}-2*\pgfkeysvalueof{/pgf/inner xsep},
   FIT/.style = {draw, dashed, inner sep=0.5mm, fit=#1},
 box/.default = 19mm
    \begin{scope}[every node/.append style={box, on chain}]
\node (r1c1)                {1};
\node (r1c2)                {2};
\node (r1c3)    [draw=none] {\dots};
\node (r1c4)                {$n$};
\node (r2c1)    [below=of r1c1] {A};
\node (r2c2)                    {B};
\node (r2c3)   [draw=none]      {\dots};
\node (r2c4)                    {X};
\node[FIT=(r1c1) (r2c1), label=text 1] {};
\node[FIT=(r1c2) (r2c2), label=text 2] {};
\node[FIT=(r1c4) (r2c4), label=text $n$] {};
\path   let \p1 = ($(r1c4.east)-(r1c1.west)$),
            \n1 = {veclen(\x1,\y1)} in
    node (r3c1) [box=\n1, below right=1mm and 0mm of r2c1.south west]
    node (r4c1) [box=\n1, below=of r3c1]    {Bottom};
\path[draw=gray, very thick, Straight Barb-Straight Barb]
    ([xshift=7mm] r1c4.north east) node[below right] {Up}
    ([xshift=7mm] r4c1.south east) node[above right] {Down};

enter image description here

  • i define common style with parameter for minimum width and calculation of text width from minimum widthfor all nodes. for narrower one -for smaller ones is defined default size 19 mm, for wider is defined by calculation
  • for dashed nodes is used ˙fit library
  • for font size in boxes i remove your selection \scriptsize. to my opinion the block diagram is now more nice.
  • Thanks. It's weird, this MWE works by its own in a new document, but when I copy the tikzpicture portion into a beamer document (with calc, chains, and fit imported), it throws this error: You meant to type ## instead of #, right? Or maybe a } was forgotten somewhere earlier, and things are all screwed up? I'm going to assume that you meant ##. ! Illegal parameter number in definition of \iterate. Any idea why? – MLister Jan 9 '19 at 9:25
  • 1
    @MLister, you not mentioned, that you use beamer. defining styles in beamer is not straightforward, at least you need add to frame option fragile ... i will change my mwe to beamer documentclass asap – Zarko Jan 9 '19 at 9:29
  • sorry my bad, I didn't realize it'd make a difference. Btw, how can I add a short text at the top of each dashed box, as well as the double arrow to the right of the stack? Thanks again. – MLister Jan 9 '19 at 9:32
  • still the same error, and I think in the new code \begin{center} and \end{center} are misaligned. Taking them out gives the same error as before, and it doesn't seem the current MWE is for beamer usage? – MLister Jan 9 '19 at 19:27
  • @MLister, your observation is correct. by mistake i didn't upload correct version of corrections of the original code. now should be ok (tested twice). – Zarko Jan 9 '19 at 22:16

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.