4

I am trying to make figures like the following:

I need flexible code that will scale well for more complex figures with many more rectangles (but the minimal example is as above).

This is my beginner's solution using \usetikzlibrary{positioning}:

\begin{tikzpicture}
\node[draw,rectangle,minimum width=7cm,minimum height=1.2cm] (n1) {(1)};
\node[draw,rectangle,minimum width=4cm,minimum height=0.9cm,above=0 of n1.north west,anchor=south west,node distance=0] (n21) {(2,1)};
\node[draw,rectangle,minimum width=3cm,minimum height=0.9cm,right=0 of n21.east,anchor=west,node distance=0] (n22) {(2,2)};
\end{tikzpicture}

Several issues here:

  • Separator lines between adjacent rectangles get drawn twice (visible when zooming close)
  • I have to take care manually that 4+3=7 so the widths add up. I would prefer a solution where I only indicate the relative position of vertical separators, i.e., 4/7=0.571
  • I need to indicate the minimum height for each rectangle on the same line
  • The extensive use of positioning keys and anchors makes the code cumbersome

I am aware of Nested rectangles with different widths. However I need the rectangles to be nodes (not paths) because I need to fit text into them.

In the TikZ manual I didn't find any builtin method that would allow me to do exactly this. So I'd be thankful for indications on how to improve this code.

4
  • 1
    Why tikz? Why not just a tabular?
    – Werner
    Apr 8 '15 at 20:40
  • I have made the example a minimal one. In the final drawing a need to place some more things on the picture which I cannot do with tabular
    – jens
    Apr 8 '15 at 20:47
  • 1
    Is this an option tex.stackexchange.com/questions/64418/… ?
    – percusse
    Apr 8 '15 at 20:51
  • @percusse Thanks for pointing me to TikZ chains. Looks nice but doesn't fully serve my purpose. Mostly because you don't manually control the width of each rectangle. Instead, each rectangle gets a width commensurate to its text content, and the last one (labeled "next") is stretched to match the right border.
    – jens
    Apr 9 '15 at 13:18
5

Now a TiKZ solution:

I suppose that all rectangles in a row have same height. Every row is declared in a scope with y=row height shifted according lower rows. Every node is defined to fit its bottom left and top right coordinates but only x coordinate changes because bottom left is at y=0 and top right is always at y=1. This way there's no need for minimum width or minimum height definitions. Text inside nodes is drawn with label=center:...

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{fit}

\begin{document}
\begin{tikzpicture}[every fit/.style={inner sep=0pt, outer sep=0pt, draw}]

\begin{scope}[y=1.5cm]
\node [fit={(0,0) (7,1)}, label=center:{(1,1)}] {};
\end{scope}

\begin{scope}[yshift=1.5cm,y=1cm]
\node [fit={(0,0) (4,1)}, label=center:{(2,1)}] {};
\node [fit={(4,0) (7,1)}, label=center:{(2,2)}] {};
\end{scope}

\begin{scope}[yshift=2.5cm,y=0.8cm]
\node [fit={(0,0) (2,1)}, label=center:{(3,1)}] {};
\node [fit={(2,0) (5,1)}, label=center:{(3,2)}] {};
\node [fit={(5,0) (7,1)}, label=center:{(3,3)}] {};
\end{scope}
\end{tikzpicture}
\end{document}

enter image description here

1
  • 1
    Nice! This comes close to what I am looking for so I'll accept it as an answer. bytefield is also interesting but seems to be designed for network protocols only. TikZ on the other hand will allow me to draw a few extra things on top of my diagram.
    – jens
    Apr 9 '15 at 13:12
5

From its abstract:

The bytefield package helps the user create illustrations for network protocol specifications and anything else that utilizes fields of data.

A simple example like yours can be drawn with

\documentclass[border=2mm]{standalone}
\usepackage{bytefield}
\begin{document}
\bytefieldsetup{bitheight=1cm}
\begin{bytefield}[bitwidth=1cm]{7}
\bitbox{4}{(2,1)} & \bitbox{3}{(2,2)} \\\bytefieldsetup{bitheight=1.2cm}%
\wordbox{1}{(1,1)}
\end{bytefield}

\begin{bytefield}[bitwidth=1cm]{7} declares the longest retangle width in bits (7) and the bit width in an optional parameter.

After that every box is declared with \bitbox{box width in bits}{box contents}. A whole line box is declared with \wordbox{lines height}{box contents}.

bitheight fixes every line height, but can be adjusted for every row

enter image description here

A more complex example taken from bytefield documentation

\documentclass[border=2mm]{standalone}
\usepackage{bytefield}
\begin{document}
\begin{bytefield}[bitwidth=1.1em]{32}
\bitheader{0-31} \\
\begin{rightwordgroup}{RTP \\ Header}
\bitbox{2}{V=2} & \bitbox{1}{P} & \bitbox{1}{X}
& \bitbox{4}{CC} & \bitbox{1}{M} & \bitbox{7}{PT}
& \bitbox{16}{sequence number} \\
\bitbox{32}{timestamp}
\end{rightwordgroup} \\
\bitbox{32}{synchronization source (SSRC) identifier} \\
\wordbox[tlr]{1}{contributing source (CSRC) identifiers} \\
\wordbox[blr]{1}{$\cdots$} \\
\begin{rightwordgroup}{RTP \\ Payload}
\wordbox[tlr]{3}{MPEG-4 Visual stream (byte aligned)} \\
\bitbox[blr]{16}{}
& \bitbox{16}{\dots\emph{optional} RTP padding}
\end{rightwordgroup}
\end{bytefield}
\end{document}

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.