# Draw table-looking layout with axes

I need to draw a container bay layout like the one below. I am a complete noob with TIKZ.

You can see it as a kind of table with axes. Both axes have variable sizes, and it would be good for the numbers to start with 1 instead of 0. I will need to create layouts like this often so creating a template that takes an input like this

{}{6}{3,9,0}{5}{4,1,2,7}{8}


would be nice. You can structure it differently, but you get the idea. The boxes will always contain number 0-99, no text.

Additionally, could you please describe how to edit one of the boxes to be shaded (grayish), crossed out (diagonal lines in the background). I would ask it in a new question, but this is closely related to the type of element you use to draw.

-
You don't need TikZ to do something so simple as this. The good old LaTeX picture environment would suffice. –  Thruston Mar 3 '14 at 12:47
Tikz was just my first idea where I had a few attempts. Thank you, I will have a look at the picture package –  Alan Mar 3 '14 at 19:21

A possible solution. Key points: double foreach and keeping track of blocks through apposite names.

\documentclass[tikz,border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{backgrounds,calc,patterns}

\tikzset{container/.style={
draw,
minimum size=1cm,
anchor=south west
},
bg box/.style={
container,
anchor=center
}
}

\newcommand{\containerbay}[1]{
\foreach \x[count=\xi from 0] in {#1}{
\foreach \y[count=\yi from 0] in \x{
\node[container] (box-\xi-\yi) at (\xi,\yi){\y};
}
}
}

\newcommand{\drawxaxes}[1]{
\draw (0,0) -- (#1,0);
\foreach \x[remember=\x as \lastx] in {0,1,...,#1}{
\ifnum\x>0
\draw[xshift=0.5\pgflinewidth] (\x,0)--(\x,-0.1);
\node[below] at ($(\x,0)-(0.5,0)$) {\lastx};
\fi
}
}

\newcommand{\drawyaxes}[1]{
\draw (0,0) -- (0,#1);
\foreach \y[remember=\y as \lasty] in {0,1,...,#1}{
\ifnum\y>0
\draw (0.1,\y)--(-0.1,\y);
\node[left] at ($(0,\y)-(0,0.5)$) {\lasty};
\fi
}
}

\begin{document}
\begin{tikzpicture}
\drawxaxes{6}
\drawyaxes{4}
\containerbay{{},{6},{3,9,0},{5},{4,{},2,7},{8}}% use {} for void elements

% customization: each block is identified by the name "box-<row>-<column>"
\begin{scope}[on background layer,bg box]% style bg box for background
\node[fill=blue!20] at (box-1-0){};
\node[top color=green!1,bottom color=green!50!lime!50] at (box-2-1){};
\node[pattern=north west lines, pattern color=red!40] at (box-3-0){};
\node[inner color=green!1,outer color=magenta!50!violet!50] at (box-4-1){};
\node[pattern=crosshatch, pattern color=orange!60] at (box-4-3){};
\end{scope}
\end{tikzpicture}
\end{document}


The result:

-
Awesome.. Just what I needed ;) tnx –  Alan Mar 3 '14 at 19:19

This is another alternative solution seeking help from pgfplotstable and table of number is prepared for read-in, The number 100 means no box required whilst 0-99 are the numbers for boxes. The solution also assumes each number has a designated color through definition.

Code

\documentclass[border=1cm]{standalone}
\usepackage{pgfplotstable}
\usepackage{tikz}
\usetikzlibrary{positioning}

100, 100, 100, 100,   7, 100
100, 100,   0, 100,   2, 100
100, 100,   9, 100,   1, 100
100,   6,   3,   5,   4,   8
}\mycolor
\newcommand\m{4}  % number of rows
\newcommand\n{6}  % number of columns
\definecolor{c0}{HTML}{54FF00}
\definecolor{c1}{HTML}{BBFFFF}
\definecolor{c2}{HTML}{FF0000}
\definecolor{c3}{HTML}{0048FF}
\definecolor{c4}{HTML}{54FFAA}
\definecolor{c5}{HTML}{1FFFFF}
\definecolor{c6}{HTML}{FF00AA}
\definecolor{c7}{HTML}{0048FE}
\definecolor{c8}{HTML}{0048FC}
\definecolor{c9}{HTML}{AAFFFF}

\begin{document}

\begin{tikzpicture}
\foreach \x[count=\xi from 0] in {1,...,\n}{
\foreach \y[count=\yi from 0] in {1,...,\m}{
\begin{scope}[shift={(-1,4)}] % for alignment of x-y axis
\pgfplotstablegetelem{\yi}{\xi}\of{\mycolor}
\ifnum\pgfplotsretval = 100
\path[shift={(\x,-\y)}] (0,0) rectangle (1,1);
\else
\draw[shift={(\x,-\y)},fill=c\pgfplotsretval] (0,0) rectangle (1,1) node[xshift=-0.5cm,yshift=-0.5cm]{\pgfplotsretval};
\fi
\end{scope}
\draw[thick](\x,2pt)--(\x,-2pt) (\xi,0)--(\x,0)node[midway,below]{\xi};
\draw[thick](2pt,\y)--(-2pt,\y) (0,\yi)--(0,\y)node[midway,left]{\yi};
}
}
\end{tikzpicture}
\end{document}

-
Thank you for your solution. –  Alan Mar 3 '14 at 19:20

A solution via MetaPost, which limits itself to the OP's wishes (grey shading, hatching with diagonal lines).

The main macro, table_looking_layout, takes two infinite arguments: the heights of each vertical bars (or the number of squares in each bar) and the numbers located inside each square, and draw these bars with their numbers. This macro also checks that the heights sum is equal to the number of squares.

The two others macros, fill_with_shade and fill_with_hatching, as their names hint, fill the list of squares given as second argument, respectively with the gray shading and hatching given as first argument.

To be run with the metafun format:

mpost --mem=metafun file.mp


Hope that helps…

input latexmp; input hatching;
setupLaTeXMP(options="12pt", textextlabel=enable, mode=rerun);
u := 1.5cm;

numeric N[][]; path P[][];

% Main macro. First argument: height of the successive bars.
% Second argument: the numbers inside
vardef table_looking_layout (text s) (text t) =

save i, j, k, total, number, nb_bars, height_bar, height_bar_max;

i = 0;
height_bar_max = 0;
for $= s: i := i+1; height_bar[i] =$;
if height_bar_max < $: height_bar_max :=$; fi;
endfor;
nb_bars = i;

j = 0;
for $= t: j := j+1; number[j] =$;
endfor;
total = j;

% Draw the bars, check before if arguments are coherent (else does nothing)
if total = height_bar[1] for l = 2 upto nb_bars: + height_bar[l] endfor:
k = 0;
for m = 1 upto nb_bars:
for n = 1 upto height_bar[m]:
k := k+1;
P[m][n] := (m-1, n-1)*u -- (m-1, n)*u -- (m, n)*u -- (m, n-1)*u -- cycle;
unfill P[m][n]; draw P[m][n];
N[m][n] := number[k];
label(decimal N[m][n], center P[m][n]);
endfor;
endfor;
draw origin -- (nb_bars*u, 0) withcolor white; draw origin -- (nb_bars*u, 0);
draw origin -- (0, height_bar_max)*u withcolor white; draw origin -- (0, height_bar_max)*u;
for m = 1 upto nb_bars:
label.bot(decimal m, (0.5[m-1, m]*u, 0));
endfor;
for n = 1 upto height_bar_max:
draw (-3bp, n*u) -- (3bp, n*u);
label.lft(decimal n, (0, 0.5[n-1, n]*u));
endfor;
else:
label("Data error!", origin);
fi;
enddef;

% fill list t of squares (bar x, height y) with color c
for z = t:
x := xpart z; y:= ypart z;
fill P[x][y] withcolor c; draw P[x][y]; label(decimal N[x][y], center P[x][y]);
endfor;
enddef;

% fill list t of squares (bar x, height y) with hatching c
def fill_with_hatching(expr c)(text t) =
for z = t:
x := xpart z; y:= ypart z;
unfill P[x][y]; hatchfill P[x][y] withcolor c; draw P[x][y];
unfill boundingbox thelabel(decimal N[x][y], center P[x][y]) enlarged 1bp;
label(decimal N[x][y], center P[x][y]);
endfor;
enddef;

beginfig(1);
% OP's Example
table_looking_layout (1, 3, 1, 4, 1) (6, 3, 9, 0, 5, 4, 1, 2, 7, 8);
fill_with_shade(0.8white, (2, 2), (3, 1), (4, 3));
fill_with_hatching((45, 1mm, -0.5bp), (1, 1), (4, 2));
endfig;
end.


-